[{"data":1,"prerenderedAt":760},["ShallowReactive",2],{"bootstrap":3,"blog-selling-gift-cards-with-commerce-layer":277},{"navigation":4,"globalConfig":196,"forms":218},{"headerSections":5,"headerFooterLinks":67,"footer":76,"legalLinks":153,"socialLinks":176},[6,39,44,50,57,62],{"hasSubMenu":7,"title":8,"links":9,"columns":38},true,"Product",[10,20,26,32],{"showTag":11,"_modelApiKey":12,"text":13,"subtitle":14,"icon":15,"isExternal":11,"link":16,"openForm":11},false,"navigation_link","Universal checkout","Sell anywhere","globe-simple",{"_modelApiKey":17,"slug":18,"title":19},"page","universal-checkout","Universal Checkout",{"showTag":11,"_modelApiKey":12,"text":21,"subtitle":22,"icon":23,"isExternal":11,"link":24,"openForm":11},"Distributed OMS","Manage orders","package",{"_modelApiKey":17,"slug":25,"title":21},"distributed-oms",{"showTag":11,"_modelApiKey":12,"text":27,"subtitle":28,"icon":29,"isExternal":11,"link":30,"openForm":11},"Promotion engine","Automated discounts","seal-percent",{"_modelApiKey":17,"slug":31,"title":27},"promotion-engine",{"showTag":11,"_modelApiKey":12,"text":33,"subtitle":34,"icon":35,"isExternal":11,"link":36,"openForm":11},"POS system","Operate stores","devices",{"_modelApiKey":17,"slug":37,"title":33},"pos-system",2,{"hasSubMenu":11,"showTag":11,"_modelApiKey":12,"text":40,"isExternal":11,"link":41,"openForm":11,"title":40},"Pricing",{"_modelApiKey":42,"slug":43},"pricing_page","pricing",{"hasSubMenu":11,"showTag":11,"_modelApiKey":12,"text":45,"isExternal":11,"link":46,"openForm":11,"title":45},"Customers",{"_modelApiKey":47,"slug":48,"title":49},"customer_landing_page","customers","Customers page",{"hasSubMenu":11,"showTag":11,"_modelApiKey":12,"text":51,"isExternal":11,"link":52,"openForm":11,"form":54,"title":51},"Partners",{"_modelApiKey":17,"slug":53,"title":51},"partners",{"_modelApiKey":55,"slug":53,"name":56},"form","PartnersForm",{"hasSubMenu":11,"showTag":11,"_modelApiKey":12,"text":58,"label":59,"isExternal":7,"url":60,"openForm":11,"title":61},"Docs Hub","Learn more","https:\u002F\u002Fdocs.commercelayer.io\u002F","Docs",{"hasSubMenu":11,"showTag":11,"_modelApiKey":12,"text":63,"isExternal":11,"link":64,"openForm":11,"title":63},"Blog",{"_modelApiKey":65,"slug":66},"blog_landing_page","blog",[68,72],{"text":69,"link":70},"Sign in",{"_modelApiKey":12,"text":69,"isExternal":7,"url":71,"openForm":11},"https:\u002F\u002Fdashboard.commercelayer.io\u002Fsign_in",{"text":73,"link":74},"Sign up for free",{"_modelApiKey":12,"text":73,"isExternal":7,"url":75,"openForm":11},"https:\u002F\u002Fdashboard.commercelayer.io\u002Fsign_up",[77,89,109,132],{"hasSubMenu":7,"title":8,"links":78},[79,81,83,85,87],{"showTag":11,"_modelApiKey":12,"text":13,"subtitle":14,"icon":15,"isExternal":11,"link":80,"openForm":11},{"_modelApiKey":17,"slug":18,"title":19},{"showTag":11,"_modelApiKey":12,"text":21,"subtitle":22,"icon":23,"isExternal":11,"link":82,"openForm":11},{"_modelApiKey":17,"slug":25,"title":21},{"showTag":11,"_modelApiKey":12,"text":27,"subtitle":28,"icon":29,"isExternal":11,"link":84,"openForm":11},{"_modelApiKey":17,"slug":31,"title":27},{"showTag":11,"_modelApiKey":12,"text":33,"subtitle":34,"icon":35,"isExternal":11,"link":86,"openForm":11},{"_modelApiKey":17,"slug":37,"title":33},{"showTag":11,"_modelApiKey":12,"text":40,"isExternal":11,"link":88,"openForm":11},{"_modelApiKey":42,"slug":43},{"hasSubMenu":7,"title":90,"links":91},"Resources",[92,94,99,104,107],{"showTag":11,"_modelApiKey":12,"text":93,"isExternal":7,"url":60,"openForm":11},"Documentation",{"showTag":11,"_modelApiKey":12,"text":95,"label":95,"isExternal":11,"link":96,"openForm":11},"Agentic Commerce",{"_modelApiKey":17,"slug":97,"title":98},"agentic-commerce-whitepaper","Agentic Commerce Whitepaper",{"showTag":11,"_modelApiKey":12,"text":100,"isExternal":11,"link":101,"openForm":11},"Core concepts",{"_modelApiKey":17,"slug":102,"title":103},"headless-commerce","Headless commerce",{"showTag":11,"_modelApiKey":12,"text":105,"isExternal":7,"url":106,"openForm":11},"Changelog","https:\u002F\u002Fdocs.commercelayer.io\u002Fchangelog\u002F",{"showTag":11,"_modelApiKey":12,"text":63,"isExternal":11,"link":108,"openForm":11},{"_modelApiKey":65,"slug":66},{"hasSubMenu":7,"title":110,"links":111},"Company",[112,116,118,121,126],{"showTag":11,"_modelApiKey":12,"text":113,"isExternal":11,"link":114,"openForm":11},"Vision",{"_modelApiKey":17,"slug":115,"title":113},"vision",{"showTag":11,"_modelApiKey":12,"text":45,"isExternal":11,"link":117,"openForm":11},{"_modelApiKey":47,"slug":48,"title":49},{"showTag":11,"_modelApiKey":12,"text":51,"isExternal":11,"link":119,"openForm":11,"form":120},{"_modelApiKey":17,"slug":53,"title":51},{"_modelApiKey":55,"slug":53,"name":56},{"showTag":11,"_modelApiKey":12,"text":122,"isExternal":11,"link":123,"openForm":11},"Security",{"_modelApiKey":17,"slug":124,"title":125},"security","Security at Commerce Layer",{"showTag":11,"_modelApiKey":12,"text":127,"label":128,"isExternal":11,"openForm":7,"form":129},"Giveback","Giveback program",{"_modelApiKey":55,"slug":130,"name":131},"giveback","GivebackForm",{"hasSubMenu":7,"title":133,"links":134},"Get in touch",[135,140,145,149],{"showTag":11,"_modelApiKey":12,"text":136,"isExternal":11,"openForm":7,"form":137},"Contact",{"_modelApiKey":55,"slug":138,"name":139},"contact","ContactUsForm",{"showTag":11,"_modelApiKey":12,"text":141,"isExternal":11,"openForm":7,"form":142},"Book a demo",{"_modelApiKey":55,"slug":143,"name":144},"demo","RequestDemoForm",{"showTag":11,"_modelApiKey":12,"text":146,"label":147,"isExternal":7,"url":148,"openForm":11},"Support","Email support","mailto:support@commercelayer.io",{"showTag":11,"_modelApiKey":12,"text":150,"label":151,"isExternal":7,"url":152,"openForm":11},"Community","Discord community","https:\u002F\u002Fdiscord.gg\u002Fcommercelayer",{"hasSubMenu":7,"title":154,"links":155},"Legal",[156,161,165,169,173],{"showTag":11,"_modelApiKey":12,"text":157,"label":158,"isExternal":7,"url":159,"openForm":11,"htmlClassNames":160},"Terms","Terms and conditions","\u002Flegal-embed\u002Fterms-of-service","iubenda-nostyle no-brand iubenda-noiframe iubenda-embed",{"showTag":11,"_modelApiKey":12,"text":162,"label":163,"isExternal":7,"url":164,"openForm":11,"htmlClassNames":160},"Privacy","Privacy policy","\u002Flegal-embed\u002Fprivacy-policy",{"showTag":11,"_modelApiKey":12,"text":166,"label":167,"isExternal":7,"url":168,"openForm":11,"htmlClassNames":160},"Cookies","Cookie policy","\u002Flegal-embed\u002Fcookie-policy",{"showTag":11,"_modelApiKey":12,"text":170,"isExternal":7,"url":171,"openForm":11,"htmlClassNames":172},"Notice at collection","#","iubenda-cs-uspr-link",{"showTag":11,"_modelApiKey":12,"text":174,"isExternal":7,"url":171,"openForm":11,"htmlClassNames":175},"Privacy preferences","iubenda-cs-preferences-link",[177,180,184,188,192],{"title":178,"type":179,"url":152,"isExternal":7},"Discord","discord-logo",{"title":181,"type":182,"url":183,"isExternal":7},"Github","github","https:\u002F\u002Fgithub.com\u002Fcommercelayer",{"title":185,"type":186,"url":187,"isExternal":7},"Bluesky","bluesky-logo","https:\u002F\u002Fbsky.app\u002Fprofile\u002Fcommercelayer.io",{"title":189,"type":190,"url":191,"isExternal":7},"X","x-logo","https:\u002F\u002Fx.com\u002Fcommercelayer",{"title":193,"type":194,"url":195,"isExternal":7},"LinkedIn","linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fcommerce-layer",{"pagesWithoutCtaPanel":197,"ctaPanel":198,"notification":208,"showApiResponseTime":11,"newsletterSignup":216},[],{"title":199,"subtitle":200,"ctas":201},"Ready to get started?","Discover how we can help your business.",[202,205],{"_modelApiKey":203,"text":204,"isExternal":7,"url":75,"openForm":11},"link","Get started for free",{"_modelApiKey":203,"text":206,"isExternal":11,"openForm":7,"form":207},"Contact us",{"_modelApiKey":55,"slug":138,"name":139},{"showNotification":7,"link":209,"linkText":210,"text":215},{"_modelApiKey":203,"text":210,"isExternal":11,"link":211,"openForm":11},"Read article",{"_modelApiKey":212,"slug":213,"title":214},"blog_post","payment-api-redesigned","Introducing our new Payments API. For humans and agents.","\u003Cp>Introducing our new Payments API. For humans and agents.\u003C\u002Fp>\n",{"ctaText":217},"Subscribe",[219,225,229,236,240,246,249,253,261,262,267,272,274],{"_modelApiKey":55,"slug":220,"pardotFormEmbedCode":221,"formEmbedMinHeight":222,"successTitle":223,"successCopy":224},"agentic-commerce","https:\u002F\u002Fcommercelayer.fillout.com\u002Ft\u002F5w4Khwgxr6us?whitepaper=agentic",520,"Thank you for your request!","We’ll be in touch soon to arrange a date and time for your personalized demo.",{"_modelApiKey":55,"slug":226,"pardotFormEmbedCode":227,"formEmbedMinHeight":228,"successTitle":223,"successCopy":224},"shopify","https:\u002F\u002Fform.fillout.com\u002Ft\u002FgVnLSmKZwRus",850,{"_modelApiKey":55,"slug":130,"pardotFormEmbedCode":230,"formEmbedMinHeight":231,"displayTitle":232,"copy":233,"successTitle":234,"successCopy":235},"https:\u002F\u002Fform.fillout.com\u002Ft\u002FmVDF8aAiofus",500,"We give back.","\u003Cp>Part of Commerce Layer&#39;s company ethos is to empathize and support one another: co-workers, customers, and community. We want to do our part to help nonprofit organizations and small businesses who may feel adversely affected by the current global economic climate, and as a result, need in-kind support to reach their customers.\u003C\u002Fp>\n\n\u003Cp>If this general description matches your organization’s needs, please tell us your story by completing the following form so we can consider helping your cause.\u003C\u002Fp>\n","Thank you!","We will contact you soon to learn more about your story.",{"_modelApiKey":55,"slug":237,"pardotFormEmbedCode":227,"formEmbedMinHeight":228,"displayTitle":238,"copy":239},"book-an-onboarding-session","Book an onboarding session","\u003Cp>Schedule some time and our devs will help you set up a Commerce Layer + Sanity store.\u003C\u002Fp>\n",{"_modelApiKey":55,"slug":241,"pardotFormEmbedCode":242,"formEmbedMinHeight":243,"displayTitle":244,"successTitle":234,"successCopy":245},"download-our-whitepaper","https:\u002F\u002Fform.fillout.com\u002Ft\u002F5YPWmy8oT7us?whitepaper=ComposableCommerce",450,"Download our whitepaper.","Check your inbox. You should receive a download link soon.",{"_modelApiKey":55,"slug":247,"pardotFormEmbedCode":248,"formEmbedMinHeight":243,"displayTitle":244,"successTitle":234,"successCopy":245},"download-the-content-and-commerce-whitepaper","https:\u002F\u002Fform.fillout.com\u002Ft\u002F5YPWmy8oT7us?whitepaper=ContentAndCommerce",{"_modelApiKey":55,"slug":250,"pardotFormEmbedCode":251,"formEmbedMinHeight":243,"displayTitle":244,"copy":252,"successTitle":234,"successCopy":245},"whitepaper","https:\u002F\u002Fform.fillout.com\u002Ft\u002F5YPWmy8oT7us?whitepaper=Jamstack","\u003Cp>Commerce Layer is the perfect platform for building commerce on the Jamstack. Convert any design into pixel perfect HTML pages. Connect a best-of-breed headless CMS. Go serverless and forget the hassle of managing complex infrastructures.\u003C\u002Fp>\n",{"_modelApiKey":55,"slug":254,"pardotFormEmbedCode":255,"formEmbedMinHeight":256,"displayTitle":257,"copy":258,"successTitle":259,"successCopy":260},"contact-links","https:\u002F\u002Fform.fillout.com\u002Ft\u002FeWPyhHGHT7us",750,"Contact us.","\u003Cp>Tell us about your project. Our team will reach out to you for a personalized offer.\u003C\u002Fp>\n","Thanks for your message!","We’ll be in touch soon to discuss your project details.",{"_modelApiKey":55,"slug":138,"pardotFormEmbedCode":255,"formEmbedMinHeight":256,"displayTitle":257,"copy":258,"successTitle":259,"successCopy":260},{"_modelApiKey":55,"slug":263,"pardotFormEmbedCode":227,"formEmbedMinHeight":228,"displayTitle":264,"successTitle":265,"successCopy":266},"demo-embed","Want to see it in action? Request a demo.","Thanks for your request!","We’ll be in touch soon to arrange a date and time for your free live demo.",{"_modelApiKey":55,"slug":53,"pardotFormEmbedCode":268,"formEmbedMinHeight":228,"displayTitle":269,"copy":270,"successTitle":234,"successCopy":271},"https:\u002F\u002Fform.fillout.com\u002Ft\u002F9MTkDWMUSqus","Become our partner.","\u003Cp>Join us and get our guidance in helping your clients succeed. Our partners are our ambassadors. We are committed to your success as much as you are.\u003C\u002Fp>\n","We will contact you soon to discuss the details of our partnership.",{"_modelApiKey":55,"slug":273,"pardotFormEmbedCode":268,"formEmbedMinHeight":228,"displayTitle":269,"copy":270,"successTitle":234,"successCopy":271},"partners-embed",{"_modelApiKey":55,"slug":143,"pardotFormEmbedCode":227,"formEmbedMinHeight":228,"displayTitle":275,"copy":276,"successTitle":265,"successCopy":266},"Get a free live demo.","\u003Cp>Get a personalized demo and learn more about what Commerce Layer can do for your company.\u003C\u002Fp>\n",{"_modelApiKey":212,"link":278,"subtitle":283,"date":283,"author":284,"additionalAuthors":294,"icon":295,"abstract":296,"tag":297,"displayTitle":279,"cardRatio":300,"featured":11,"seoMetaTags":301,"layout":365,"blogPostCarousel":303,"_seoMetaTags":721,"authors":755},{"text":279,"isExternal":11,"url":280,"link":281},"Selling gift cards with Commerce Layer.","",{"_modelApiKey":212,"slug":282},"selling-gift-cards-with-commerce-layer","July 18, 2025",{"name":285,"picture":286},"Fabrizio Picca",{"url":287,"alt":288,"title":288,"width":289,"height":289,"format":290,"focalPoint":291,"customData":293},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1614875259-commercelayeravatarsquare113f26.png","Fabrizio Picca —      Partnerships Manager at Commerce Layer",1280,"png",{"x":292,"y":292},0.5,{},[],"gift","This tutorial shows how to build a gift card purchase flow using Commerce Layer APIs, React components, hosted checkout, and Zapier for activation — fully integrated into a Next.js app.",{"color":298,"name":299},"gray","Tutorials","portrait",[302,306,310,313,317,320,323,327,331,335,338,342,346,350,354,357,361],{"attributes":303,"tag":304,"content":305},null,"title","Selling gift cards with Commerce Layer",{"attributes":307,"tag":309,"content":303},{"property":308,"content":305},"og:title","meta",{"attributes":311,"tag":309,"content":303},{"name":312,"content":305},"twitter:title",{"attributes":314,"tag":309,"content":303},{"name":315,"content":316},"description","A step-by-step tutorial that shows how to build a gift card purchase flow using Commerce Layer APIs, developer tools, and Zapier app.",{"attributes":318,"tag":309,"content":303},{"property":319,"content":316},"og:description",{"attributes":321,"tag":309,"content":303},{"name":322,"content":316},"twitter:description",{"attributes":324,"tag":309,"content":303},{"property":325,"content":326},"og:image","https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752680566-selling-gift-card-thumb.jpg?auto=format&fit=max&w=1200",{"attributes":328,"tag":309,"content":303},{"property":329,"content":330},"og:image:width","1200",{"attributes":332,"tag":309,"content":303},{"property":333,"content":334},"og:image:height","630",{"attributes":336,"tag":309,"content":303},{"name":337,"content":326},"twitter:image",{"attributes":339,"tag":309,"content":303},{"property":340,"content":341},"og:locale","en",{"attributes":343,"tag":309,"content":303},{"property":344,"content":345},"og:type","article",{"attributes":347,"tag":309,"content":303},{"property":348,"content":349},"og:site_name","Commerce Layer",{"attributes":351,"tag":309,"content":303},{"property":352,"content":353},"article:modified_time","2025-10-08T16:22:03Z",{"attributes":355,"tag":309,"content":303},{"property":356,"content":280},"article:publisher",{"attributes":358,"tag":309,"content":303},{"name":359,"content":360},"twitter:card","summary_large_image",{"attributes":362,"tag":309,"content":303},{"name":363,"content":364},"twitter:site","@commercelayer",[366,371,376,386,394,397,400,403,410,413,418,421,424,427,429,432,436,439,441,444,447,450,452,455,457,460,462,465,467,470,472,475,477,480,487,490,492,495,497,500,506,508,511,513,516,518,521,528,531,538,540,543,550,553,562,565,572,575,582,585,593,596,604,607,614,617,624,627,634,637,644,647,654,657,664,667,674,677,684,687,694,697,705,708,711,718],{"_modelApiKey":367,"icon":368,"copy":369,"color":370},"banner","bookmark","\u003Cp>This is the second of a two-part article about Commerce Layer&#39;s gift card functionality. The \u003Ca href=\"\u002Fblog\u002Fexploring-commerce-layer-gift-cards\">first part\u003C\u002Fa> explains all the internals of gift cards and is a recommended read before digging into this tutorial.\u003C\u002Fp>\n","red",{"_modelApiKey":372,"copy":373,"listStyle":374,"darkTheme":11,"buttons":375,"color":370,"indent":7},"wysiwyg","\u003Cp>We will implement a simple page where users can personalise and purchase a gift card using the Core API \u003Ca href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fcore\u002Fapi-reference\u002Fgift_cards\">gift card\u003C\u002Fa> endpoints and other open-source developer tools provided by Commerce Layer. The final result can be seen in the screenshot below. The full code is available \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fexamples\u002Ftree\u002Fmain\u002Fsolutions\u002Fgiftcard-tutorial\">on GitHub\u003C\u002Fa>.\u003C\u002Fp>\n","directional",[],{"_modelApiKey":377,"border":7,"caption":280,"image":378,"size":385,"darkTheme":11,"rounded":7,"color":370},"image_block",{"url":379,"alt":380,"title":380,"width":289,"height":381,"format":382,"focalPoint":383,"customData":384},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752241545-nextjs-app-buy-gift-card.jpg","Buy a gift card app",1174,"jpg",{"x":292,"y":292},{},"standard",{"_modelApiKey":387,"title":388,"preTitle":389,"linkText":390,"darkTheme":11,"link":391},"link_block","Buy a Gift Card app","Open-source","Fork it",{"_modelApiKey":203,"text":392,"label":280,"subtitle":280,"icon":280,"isExternal":7,"url":393,"link":303,"anchor":280,"openForm":11,"form":303,"htmlClassNames":280},"Fork it from GitHub","https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fexamples\u002Ftree\u002Fmain\u002Fsolutions\u002Fgiftcard-tutorial",{"_modelApiKey":367,"icon":395,"copy":396,"color":370},"info","\u003Cp>Let&#39;s make clear that the goal of this tutorial is not to guide you through building a full webpage (it was actually generated using Copilot in perfect vibe-coding style!), but rather to demonstrate how to use Commerce Layer APIs to purchase a gift card. As such, we’ll assume most frontend details are already in place and focus solely on the integration aspects. \u003C\u002Fp>\n",{"_modelApiKey":372,"copy":398,"listStyle":374,"darkTheme":11,"buttons":399,"color":370,"indent":11},"\u003Cp>Our simple page is a Next.js application and we are going to use Commerce Layer React Components and JS SDK to add all the needed transactional features. We will also make use of Commerce Layer hosted Checkout to place the order.\u003C\u002Fp>\n",[],{"_modelApiKey":372,"copy":401,"listStyle":374,"darkTheme":11,"buttons":402,"color":370,"indent":11},"\u003Ch3>Setting up our project\u003C\u002Fh3>\n\n\u003Cp>Fork \u003Ca href=\"https:\u002F\u002Frepohere.com\">this repository\u003C\u002Fa> in a local folder (in my case this would be \u003Ccode>giftcard-tutorial\u003C\u002Fcode>). In Visual Studio Code the result will look like this:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":11,"caption":280,"image":404,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":405,"alt":406,"title":406,"width":289,"height":407,"format":382,"focalPoint":408,"customData":409},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752243394-vs-code-01.jpg","VS Code screenshot",757,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":411,"listStyle":374,"darkTheme":11,"buttons":412,"color":370,"indent":11},"\u003Cp>The bulk of our web application lives in \u003Ccode>src\u002Fapp\u002Fpage.tsx\u003C\u002Fcode>. Let’s start setting up our project by adding some libraries, namely:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>Commerce Layer \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fcommercelayer-sdk\">JS SDK\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>Commerce Layer \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fcommercelayer-js-auth\">JS Auth\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>Commerce Layer \u003Ca href=\"https:\u002F\u002Fcommercelayer.github.io\u002Fcommercelayer-react-components\">React Components\u003C\u002Fa>\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":414,"code":415,"showLineNumbers":11,"highlightLines":280,"language":416,"size":417},"code_block","giftcard-tutorial % npm i @commercelayer\u002Fsdk @commercelayer\u002Fjs-auth @commercelayer\u002Freact-components\n\nadded 64 packages, and audited 405 packages in 17s\n\n146 packages are looking for funding\n  run `npm fund` for details\n\nfound 0 vulnerabilities","shell","Wide",{"_modelApiKey":372,"copy":419,"listStyle":374,"darkTheme":11,"buttons":420,"color":370,"indent":11},"\u003Ch3>Setting up Cloudinary as allowed source for images\u003C\u002Fh3>\n\n\u003Cp>We are storing the AI generated designs on Cloudinary (you can use whatever service you want). To do so, beside uploading the images on the service, we need to update Next.js configuration to allow an external origin for images:\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":422,"showLineNumbers":11,"highlightLines":280,"language":423,"size":417},"import type { NextConfig } from \"next\";\n\nconst nextConfig: NextConfig = {\n  \u002F* config options here *\u002F\n  images: {\n    domains: [\"res.cloudinary.com\"],\n  },\n};\n\nexport default nextConfig;","typescript",{"_modelApiKey":372,"copy":425,"listStyle":374,"darkTheme":11,"buttons":426,"color":370,"indent":11},"\u003Cp>Now that we have all we need let’s start adding commerce capabilities to our simple page!\u003C\u002Fp>\n\n\u003Ch3>Adding Commerce Layer functionalities\u003C\u002Fh3>\n\n\u003Cp>The first thing to do is to wrap our application with the \u003Ccode>CommerceLayer\u003C\u002Fcode> React component. The presence of this component is mandatory in order for all the other components that we are going to use to work properly. \u003C\u002Fp>\n\n\u003Cp>Update \u003Ccode>src\u002Fapp\u002Flayout.tsx\u003C\u002Fcode> as follows:\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":428,"showLineNumbers":11,"highlightLines":280,"language":423,"size":417},"import type { Metadata } from \"next\";\nimport { Geist, Geist_Mono } from \"next\u002Ffont\u002Fgoogle\";\nimport \".\u002Fglobals.css\";\nimport { CommerceLayer } from \"@commercelayer\u002Freact-components\";\n\nconst geistSans = Geist({\n  variable: \"--font-geist-sans\",\n  subsets: [\"latin\"],\n});\n\nconst geistMono = Geist_Mono({\n  variable: \"--font-geist-mono\",\n  subsets: [\"latin\"],\n});\n\nexport const metadata: Metadata = {\n  title: \"Create Next App\",\n  description: \"Generated by create next app\",\n};\n\nexport default function RootLayout({\n  children,\n}: Readonly\u003C{\n  children: React.ReactNode;\n}>) {\n  return (\n    \u003CCommerceLayer accessToken={\u003CYOUR TOKEN HERE>}>\n      \u003Chtml lang=\"en\">\n        \u003Cbody\n          className={`${geistSans.variable} ${geistMono.variable} antialiased`}\n        >\n          {children}\n        \u003C\u002Fbody>\n      \u003C\u002Fhtml>\n    \u003C\u002FCommerceLayer>\n  );\n}",{"_modelApiKey":372,"copy":430,"listStyle":374,"darkTheme":11,"buttons":431,"color":370,"indent":11},"\u003Cp>As you see we have a placeholder for the token. Let’s provide a function that returns a \u003Ca href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fcore\u002Fapi-credentials#sales-channel\">sales channel\u003C\u002Fa> token that can be used to purchase a gift card. \u003C\u002Fp>\n\n\u003Cp>First, let’s create \u003Ccode>lib\u003C\u002Fcode> folder under \u003Ccode>src\u003C\u002Fcode> and add a \u003Ccode>commercelayer.ts\u003C\u002Fcode> file to it, this will contain all the helpers we’ll need throughout the implementation of the tutorial.\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":433,"showLineNumbers":11,"highlightLines":280,"language":434,"size":435},"src\n +-app\n\t  +-lib\n\t     +-commercelayer.ts","javascript","Standard",{"_modelApiKey":372,"copy":437,"listStyle":374,"darkTheme":11,"buttons":438,"color":370,"indent":11},"\u003Cp>Inside our helper file let’s add a function to retrieve a token using the \u003Ccode>js-auth\u003C\u002Fcode> library. Let give a look at the code:\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":440,"showLineNumbers":11,"highlightLines":280,"language":434,"size":417},"import { authenticate } from '@commercelayer\u002Fjs-auth'\n\nconst CL_CLIENT_ID = process.env.NEXT_PUBLIC_CL_CLIENT_ID\n\nif (!CL_CLIENT_ID) {\n  throw new Error('NEXT_PUBLIC_CL_CLIENT_ID is not defined in the environment variables')\n}\n\ninterface TokenData {\n  accessToken: string\n  expiresAt: number\n}\n\nlet tokenData: TokenData | null = null\n\nexport async function getValidToken() {\n  const auth = await authenticate('client_credentials', {\n    clientId: CL_CLIENT_ID!,\n    scope: 'market:code:us',\n  })\n  \n  return auth.accessToken\n}",{"_modelApiKey":372,"copy":442,"listStyle":374,"darkTheme":11,"buttons":443,"color":370,"indent":11},"\u003Cp>Every time the page is loaded the \u003Ccode>getValidToken()\u003C\u002Fcode> function will return a fresh token using the standard Commerce Layer \u003Ca href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fcore\u002Fauthentication\">OAuth 2.0\u003C\u002Fa> flow.\u003C\u002Fp>\n",[],{"_modelApiKey":367,"icon":445,"copy":446,"color":370},"warning","\u003Cp>This is definitely not the most efficient way to get a token, you probably want to cache your token and referesh it when needed instead of asking every time for a new one. Do not use this code in production!\u003C\u002Fp>\n",{"_modelApiKey":372,"copy":448,"listStyle":374,"darkTheme":11,"buttons":449,"color":370,"indent":11},"\u003Cp>Please also notice that our helper file makes use of an environment variable to store the client ID, needed to get a sales channel token:\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":451,"showLineNumbers":11,"highlightLines":280,"language":416,"size":417},"NEXT_PUBLIC_CL_CLIENT_ID=y0UR-cL13Nt-1D-Qd4-jd7_F_Gk",{"_modelApiKey":372,"copy":453,"listStyle":374,"darkTheme":11,"buttons":454,"color":370,"indent":11},"\u003Cp>Now that we have a way to get a token, let’s pass it to our application:\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":456,"showLineNumbers":11,"highlightLines":280,"language":434,"size":417},"import { getValidToken } from \"@\u002Flib\u002Fcommercelayer\";\n\n...\n\nexport default async function RootLayout({\n  children,\n}: Readonly\u003C{\n  children: React.ReactNode;\n}>) {\n  return (\n    \u003CCommerceLayer accessToken={await getValidToken()}>\n      \u003Chtml lang=\"en\">\n        \u003Cbody\n          className={`${geistSans.variable} ${geistMono.variable} antialiased`}\n        >\n          {children}\n        \u003C\u002Fbody>\n      \u003C\u002Fhtml>\n    \u003C\u002FCommerceLayer>\n  );\n}",{"_modelApiKey":372,"copy":458,"listStyle":374,"darkTheme":11,"buttons":459,"color":370,"indent":11},"\u003Cp>From this point on our frontend is &quot;connected&quot; to Commerce Layer!\u003C\u002Fp>\n\n\u003Cp>Following the theory explained in the \u003Ca href=\"\u002Fblog\u002Fexploring-commerce-layer-gift-cards\">first part\u003C\u002Fa> of this guide, we know that a gift card can be created on the fly using the \u003Ccode>\u002Fapi\u002Fgift_cards\u003C\u002Fcode> endpoint.\u003C\u002Fp>\n\n\u003Cp>The flow will then be:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>A customer lands on the page.\u003C\u002Fli>\n\u003Cli>The customer personalizes the gift card by setting all the attributes found in the page form.\u003C\u002Fli>\n\u003Cli>A gift card is created in Commerce Layer.\u003C\u002Fli>\n\u003Cli>The customer proceeds to payment and buys the gift card.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Ch4>Creating the gift card\u003C\u002Fh4>\n\n\u003Cp>Let’s see how to create the gift card in Commerce Layer using the page form data.\u003C\u002Fp>\n\n\u003Cp>As the customer inputs data in the form we store everything using state variables:\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":461,"showLineNumbers":11,"highlightLines":280,"language":434,"size":417},"const [amount, setAmount] = useState\u003Cnumber | \"\">(presetAmounts[0]);\nconst [customAmount, setCustomAmount] = useState(\"\");\nconst [selectedDesign, setSelectedDesign] = useState(designs[0].id);\nconst [recipient, setRecipient] = useState(\"\");\nconst [message, setMessage] = useState(\"\");",{"_modelApiKey":372,"copy":463,"listStyle":374,"darkTheme":11,"buttons":464,"color":370,"indent":11},"\u003Cp>So what we are going to do is basically triggering gift card creation when the customer clicks on the \u003Cem>Purchase\u003C\u002Fem> button using the data stored in the state variables above.\u003C\u002Fp>\n\n\u003Cp>In our \u003Ccode>page.tsx\u003C\u002Fcode> we arleady have an handler for this event:\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":466,"showLineNumbers":11,"highlightLines":280,"language":434,"size":417},"const handlePurchase = (e: React.FormEvent) => {\n   e.preventDefault();\n   \u002F\u002F Placeholder: Add purchase logic here\n   alert(\"Gift card purchased! (Demo)\");\n};",{"_modelApiKey":372,"copy":468,"listStyle":374,"darkTheme":11,"buttons":469,"color":370,"indent":11},"\u003Cp>What we are going to do is replacing the placeholder with the logic to:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>create the gift card\u003C\u002Fli>\n\u003Cli>redirecting to checkout page\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>Let’s start adding to our helper file \u003Ccode>commercelayer.ts\u003C\u002Fcode> two things:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>a new interface \u003Ccode>GiftCardData\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>a function \u003Ccode>createGiftCard\u003C\u002Fcode> that takes in input gift card data and an SDK client\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":414,"code":471,"showLineNumbers":11,"highlightLines":280,"language":434,"size":417},"...\n\nexport interface giftCardData {\n    amount: number | string\n    design: string\n    recipientEmail: string\n    message: string\n}\n\nexport async function createGiftCard(data: GiftCardData, client: CommerceLayerClient|undefined) {\n    if (!client) {\n        throw new Error(\"CommerceLayer client is not defined\");\n    }\n    return client.gift_cards.create({\n        rechargeable: false,\n        single_use: false,\n        balance_cents: typeof data.amount === 'number' ? data.amount * 100 : parseFloat(data.amount) * 100,\n        image_url: data.design,\n        recipient_email: data.recipientEmail,\n        metadata:{\n            message: data.message\n        }\n    })\n}",{"_modelApiKey":372,"copy":473,"listStyle":374,"darkTheme":11,"buttons":474,"color":370,"indent":11},"\u003Cp>Our function just wraps an sdk call to our \u003Ccode>gift_card\u003C\u002Fcode> endpoint passing the data collected so far.\u003C\u002Fp>\n\n\u003Cp>Also it sets the gift card as not rechargeable and allowed for multiple use.\u003C\u002Fp>\n\n\u003Cp>It’s time to add this function to the handler of the \u003Cem>Purchase\u003C\u002Fem> button:\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":476,"showLineNumbers":11,"highlightLines":280,"language":434,"size":417},"\"use client\";\nimport { createGiftCard, GiftCardData } from \"@\u002Flib\u002Fcommercelayer\";\n...\nimport { useCommerceLayer } from \"@commercelayer\u002Freact-components\";\n\nconst presetAmounts = [25, 50, 100, 200];\nconst designs = [\n  { id: 1, name: \"Confetti\", image: \"https:\u002F\u002Fres.cloudinary.com\u002Fdvbqso85l\u002Fimage\u002Fupload\u002Fv1751384150\u002Fconfetti_u885gd.png\" },\n  { id: 2, name: \"Birthday\", image: \"https:\u002F\u002Fres.cloudinary.com\u002Fdvbqso85l\u002Fimage\u002Fupload\u002Fv1751384150\u002Fclassic_jqxrys.png\" },\n  { id: 3, name: \"Classic\", image: \"https:\u002F\u002Fres.cloudinary.com\u002Fdvbqso85l\u002Fimage\u002Fupload\u002Fv1751384150\u002Fbirthday_qtj5zm.png\" },\n];\n...\n\nconst handlePurchase = async (e: React.FormEvent) => {\n    e.preventDefault();\n    try {\n      const giftCardData: GiftCardData = {\n        amount: (amount === \"\" ? parseFloat(customAmount) : amount) , \n        design: designs.find(d => d.id === selectedDesign)?.image || \"\",\n        recipientEmail: recipient,\n        message: message,\n      }\n\n      const giftCard = await createGiftCard(giftCardData, sdkClient())      \n\n      alert(\"Gift card purchased! \" + giftCard.id);\n\n    } catch (error) {\n      console.error(\"Error creating gift card:\", error);\n      alert(\"An error occurred while processing your purchase. Please try again.\");\n      return;\n    }\n    \n  };\n  \n  ...",{"_modelApiKey":372,"copy":478,"listStyle":374,"darkTheme":11,"buttons":479,"color":370,"indent":11},"\u003Cp>Let’s break down the \u003Ccode>handlePurchase\u003C\u002Fcode> function:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>First of all, we create an object that contains all the form-collected gift card details.\u003C\u002Fli>\n\u003Cli>The amount is either the amount selected from the pre populated options or a custom amount if the customer entered a random number. \u003C\u002Fli>\n\u003Cli>All the rest is pretty straight forward, with the only exception of the design where we basically extract from the design collection the one identified by the selected ID.\u003C\u002Fli>\n\u003Cli>Once done we pass the object and a client to our helper function (note that we used the hook \u003Ccode>useCommerceLayer()\u003C\u002Fcode> to retrieve an instance of the SDK given the current token).\u003C\u002Fli>\n\u003Cli>For the moment we just display an alert with a message containing the gift card ID if everything went fine or display an error otherwise.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Once edited the file let’s save and test our application:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":481,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":482,"alt":483,"title":483,"width":289,"height":484,"format":382,"focalPoint":485,"customData":486},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752589292-gift-card-purchase-alert.jpg","Gift Card purchase alert",1334,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":488,"listStyle":374,"darkTheme":11,"buttons":489,"color":370,"indent":11},"\u003Cp>Boom! When we press \u003Cem>Purchase\u003C\u002Fem>, our gift card creation logic is triggered and the gift card is created in Commerce Layer as we can see trying to fetch the gift card by ID (we&#39;ll use our \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fcommercelayer-cli\">CLI\u003C\u002Fa> to do that):\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":491,"showLineNumbers":11,"highlightLines":280,"language":416,"size":417},"~ % cl get gift_card\u002FrBgKUZzNqn\n{\n  id: 'rBgKUZzNqn',\n  type: 'gift_cards',\n  status: 'draft',\n  code: 'bcd42606-fbfb-451d-b4dc-e58d47d2d2d7',\n  currency_code: 'USD',\n  initial_balance_cents: 20000,\n  initial_balance_float: 200,\n  formatted_initial_balance: '$200.00',\n  balance_cents: 20000,\n  balance_float: 200,\n  formatted_balance: '$200.00',\n  balance_max_cents: null,\n  balance_max_float: null,\n  formatted_balance_max: null,\n  balance_log: [ { datetime: '2025-07-01T15:44:28.469Z', balance_change_cents: 20000 } ],\n  usage_log: {},\n  single_use: false,\n  rechargeable: false,\n  distribute_discount: true,\n  image_url: 'https:\u002F\u002Fres.cloudinary.com\u002Fdvbqso85l\u002Fimage\u002Fupload\u002Fv1751384150\u002Fconfetti_u885gd.png',\n  expires_at: null,\n  recipient_email: 'fabrizio@commercelayer.io',\n  created_at: '2025-07-01T15:44:28.469Z',\n  updated_at: '2025-07-01T15:44:28.469Z',\n  reference: null,\n  reference_origin: null,\n  metadata: { message: 'Compliments of Commerce Layer!' }\n}",{"_modelApiKey":372,"copy":493,"listStyle":374,"darkTheme":11,"buttons":494,"color":370,"indent":11},"\u003Ch4>Purchasing the gift card\u003C\u002Fh4>\n\n\u003Cp>The next step is purchasing our gift card. This step can be further broken down in three operations:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>creating an order\u003C\u002Fli>\n\u003Cli>creating a line item for the gift card\u003C\u002Fli>\n\u003Cli>redirect the customer to the hosted checkout to purchase it\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>Let&#39;s start by adding a new helper function to \u003Ccode>commercelayer.ts\u003C\u002Fcode>:\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":496,"showLineNumbers":11,"highlightLines":280,"language":434,"size":417},"...\n\nexport async function addGiftCardToOrder(giftCard:string, client: CommerceLayerClient|undefined): Promise\u003Cstring> {\n    if (!client) {\n        throw new Error(\"CommerceLayer client is not defined\");\n    }\n    \n    const order = await client.orders.create({})\n    \n    client.line_items.create({\n        quantity: 1,\n        item: client.gift_cards.relationship(giftCard),\n        order: client.orders.relationship(order.id),\n    })\n    \n    return order.id\n}\n\n...",{"_modelApiKey":372,"copy":498,"listStyle":374,"darkTheme":11,"buttons":499,"color":370,"indent":11},"\u003Cp>The function, that takes as input the newly created gift card, wraps two operations, corresponding to the first two step listed above:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>creating a new order\u003C\u002Fli>\n\u003Cli>creating a line item for the gift card\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>This function of course is not ideal for real applications as it’s a bit opinionated (we only add gift cards to orders and we create a new order each time we create a gift card), but can work well in our example. Using the SDK we create an empty order, and right after we add a line item of type \u003Ccode>gift_cards\u003C\u002Fcode> (the line item&#39;s type is inferred by the \u003Ccode>item\u003C\u002Fcode> relationship) and we return the order ID.\u003C\u002Fp>\n\n\u003Cp>To redirect the customer to the hosted checkout page we need to generate the checkout link. Let’s add a function that does this according to the \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fmfe-checkout?tab=readme-ov-file#hosted-version\">documentation\u003C\u002Fa>:\u003C\u002Fp>\n",[],{"_modelApiKey":387,"title":501,"preTitle":389,"linkText":502,"darkTheme":11,"link":503},"React Checkout","View it on GitHub",{"_modelApiKey":203,"text":504,"label":280,"subtitle":280,"icon":280,"isExternal":7,"url":505,"link":303,"anchor":280,"openForm":11,"form":303,"htmlClassNames":280},"View on GitHub","https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fmfe-checkout",{"_modelApiKey":414,"code":507,"showLineNumbers":11,"highlightLines":280,"language":434,"size":417},"const CL_CLIENT_ID = process.env.NEXT_PUBLIC_CL_CLIENT_ID\nconst CL_ORG_SLUG = process.env.NEXT_PUBLIC_CL_ORG_SLUG\n\nif (!CL_CLIENT_ID || !CL_ORG_SLUG) {\n  throw new Error('NEXT_PUBLIC_CL_CLIENT_ID or NEXT_PUBLIC_CL_ORG_SLUG is not defined in the environment variables')\n}\n\n...\n\nexport async function getCheckoutLink(orderId: string){\n    return `https:\u002F\u002F${CL_ORG_SLUG}.commercelayer.app\u002Fcheckout\u002F${orderId}?accessToken=${await getValidToken()}`\n}",{"_modelApiKey":372,"copy":509,"listStyle":374,"darkTheme":11,"buttons":510,"color":370,"indent":11},"\u003Cp>The function needs an additional environment variable to store the Commerce Layer organization slug needed to build the hosted chekout URL:\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":512,"showLineNumbers":11,"highlightLines":280,"language":416,"size":417},"NEXT_PUBLIC_CL_CLIENT_ID=y0UR-cL13Nt-1D-Qd4-jd7_F_Gk\nNEXT_PUBLIC_CL_ORG_SLUG=your-org-slug",{"_modelApiKey":372,"copy":514,"listStyle":374,"darkTheme":11,"buttons":515,"color":370,"indent":11},"\u003Cp>Now that we have all the pieces needed in order to create an order, add the gift card to it, and get a checkout link, let’s assemble everything in the application code inside the handler of the purchase button:\u003C\u002Fp>\n",[],{"_modelApiKey":414,"code":517,"showLineNumbers":11,"highlightLines":280,"language":434,"size":417},"...\n\nconst handlePurchase = async (e: React.FormEvent) => {\n    e.preventDefault();\n    try {\n      ...\n      const giftCard = await createGiftCard(giftCardData, sdkClient())\n      const order = await addGiftCardToOrder(giftCard.id, sdkClient())\n      const checkoutLink = await getCheckoutLink(order)\n      \n      window.location.href = checkoutLink;\n\n    } catch (error) {\n      console.error(\"Error creating gift card:\", error);\n      alert(\"An error occurred while processing your purchase. Please try again.\");\n      return;\n    }\n    \n  };\n  \n  ...",{"_modelApiKey":372,"copy":519,"listStyle":374,"darkTheme":11,"buttons":520,"color":370,"indent":11},"\u003Cp>There we go! Now when the pressing the \u003Cem>Purchase\u003C\u002Fem> button a redirection to the hosted checkout page happens:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":522,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":523,"alt":524,"title":524,"width":289,"height":525,"format":382,"focalPoint":526,"customData":527},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752592290-checkout-gift-card.jpg","Checkout gift card",998,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":529,"listStyle":374,"darkTheme":11,"buttons":530,"color":370,"indent":11},"\u003Cp>Once the order is placed, the newly purchased gift card will show up in the Dashboard Gift cards app as inactive, according to the lifecycle we explained in the \u003Ca href=\"\u002Fblog\u002Fexploring-commerce-layer-gift-cards\">previous article\u003C\u002Fa>:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":532,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":533,"alt":534,"title":534,"width":289,"height":535,"format":382,"focalPoint":536,"customData":537},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752592898-new-gift-card-in-app.jpg","New gift card in app",824,{"x":292,"y":292},{},{"_modelApiKey":367,"icon":395,"copy":539,"color":370},"\u003Cp>Please note that the Gift card app shows items only in \u003Cem>inactive\u003C\u002Fem>, \u003Cem>active\u003C\u002Fem>, and \u003Cem>redeemed\u003C\u002Fem> status. This means that \u003Cem>draft\u003C\u002Fem> gift cards are not displayed.\u003C\u002Fp>\n",{"_modelApiKey":372,"copy":541,"listStyle":374,"darkTheme":11,"buttons":542,"color":370,"indent":11},"\u003Ch3>Integration with Zapier for gift card activation\u003C\u002Fh3>\n\n\u003Cp>If the creation and purchase of gift cards is entirely managed by Commerce Layer APIs, the activation might require some integration. It&#39;s always is possible to activate gift cards straight from the Dashboard Gift card app, but you probably don’t want your customer service to be flooded with phone calls asking for that.\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":544,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":545,"alt":546,"title":546,"width":289,"height":547,"format":382,"focalPoint":548,"customData":549},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752664081-gift-card-activation-2.jpg","Gift card activation via Dashboard",663,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":551,"listStyle":374,"darkTheme":11,"buttons":552,"color":370,"indent":11},"\u003Cp>The real flow should follow the steps below:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":11,"caption":280,"image":554,"size":561,"darkTheme":11,"rounded":11,"color":370},{"url":555,"alt":556,"title":556,"width":557,"height":558,"format":559,"focalPoint":303,"customData":560},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752664825-gift-card-activation-flow.svg","Gift card activation flow",1000,928,"svg",{},"slim",{"_modelApiKey":372,"copy":563,"listStyle":374,"darkTheme":11,"buttons":564,"color":370,"indent":11},"\u003Cp>To implement this flow, this is what we are going to do:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>Set up a zap in Zapier that uses one of the triggers supported by the \u003Ca href=\"https:\u002F\u002Fzapier.com\u002Fapps\u002Fcommerce-layer\u002Fintegrations\">Commerce Layer Zapier app\u003C\u002Fa> to start a workflow every time a gift card is purchased.\u003C\u002Fli>\n\u003Cli>Link this to one of actions supported by the Commerce Layer Zapier app to sends an email that notifies the recipient of the gift.\u003C\u002Fli>\n\u003Cli>Implement (still in Zapier) the endpoint the recipient will click to activate the gift card.\u003C\u002Fli>\n\u003Cli>Activate the gift card using (again) the Zapier app.\u003C\u002Fli>\n\u003C\u002Fol>\n",[],{"_modelApiKey":387,"title":566,"preTitle":567,"linkText":568,"darkTheme":11,"link":569},"Official Zapier app","Integrations","Try it",{"_modelApiKey":203,"text":570,"label":280,"subtitle":280,"icon":280,"isExternal":7,"url":571,"link":303,"anchor":280,"openForm":11,"form":303,"htmlClassNames":280},"Try it on Zapier","https:\u002F\u002Fzapier.com\u002Fapps\u002Fcommerce-layer",{"_modelApiKey":372,"copy":573,"listStyle":374,"darkTheme":11,"buttons":574,"color":370,"indent":11},"\u003Cp>First of all let’s create a set of \u003Ca href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fcore\u002Fapi-credentials#integration\">integration\u003C\u002Fa> API credentials from the Commerce Layer Dashboard (\u003Cem>Developers &gt; API Crendentials\u003C\u002Fem>):\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":576,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":577,"alt":578,"title":578,"width":289,"height":579,"format":382,"focalPoint":580,"customData":581},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752671320-zapier-app-api-credentials.jpg","Zapier app API credentials",965,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":583,"listStyle":374,"darkTheme":11,"buttons":584,"color":370,"indent":11},"\u003Ch4>Setting up the trigger\u003C\u002Fh4>\n\n\u003Cp>Now we need to create in Zapier a new zap and set up a new trigger using the Commerce Layer app. Give a meaningful name to the trigger, and select \u003Cem>New Gift Card Event\u003C\u002Fem> among the available events supported by our app:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":586,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":587,"alt":588,"title":588,"width":589,"height":590,"format":382,"focalPoint":591,"customData":592},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752673063-new-gift-card-event-zapier.jpg","New gift card event Zapier",800,668,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":594,"listStyle":374,"darkTheme":11,"buttons":595,"color":370,"indent":11},"\u003Cp>When asked for the account create one as following:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":597,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":598,"alt":599,"title":599,"width":600,"height":601,"format":382,"focalPoint":602,"customData":603},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752673361-account-creation-zapier.jpg","Account creation Zapier",910,784,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":605,"listStyle":374,"darkTheme":11,"buttons":606,"color":370,"indent":11},"\u003Cp>Hit \u003Cem>Continue\u003C\u002Fem> and in the next panel select \u003Cem>purchase\u003C\u002Fem> as the specific event we want to be notified:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":608,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":609,"alt":610,"title":610,"width":589,"height":611,"format":382,"focalPoint":612,"customData":613},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752673629-purchase-event-zapier.jpg","Purchase event Zapier",369,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":615,"listStyle":374,"darkTheme":11,"buttons":616,"color":370,"indent":11},"\u003Cp>Hit \u003Cem>Continue\u003C\u002Fem> and test your trigger. If everything went well you’ll see test data showing in the panel (remember to purchase a gift card first):\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":618,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":619,"alt":620,"title":620,"width":589,"height":621,"format":382,"focalPoint":622,"customData":623},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752675518-test-trigger-zapier.jpg","Test trigger Zapier",586,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":625,"listStyle":374,"darkTheme":11,"buttons":626,"color":370,"indent":11},"\u003Cp>The trigger is now set up. \u003C\u002Fp>\n\n\u003Ch4>Setting up the action\u003C\u002Fh4>\n\n\u003Cp>The next step is configuring the notification action triggered by the gift card purchase event. For simplicity here we’ll just use the GMail Zapier app and send a basic email to the recipient of the gift card. Once added the next step in the zap pipeline, select the GMail app and fill the fields according to your account information:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":628,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":629,"alt":630,"title":630,"width":589,"height":631,"format":382,"focalPoint":632,"customData":633},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752676053-send-email-setup-zapier.jpg","Send email setup Zapier",645,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":635,"listStyle":374,"darkTheme":11,"buttons":636,"color":370,"indent":11},"\u003Cp>In the \u003Cem>Configure\u003C\u002Fem> panel we can define how the email notification will look like:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":638,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":639,"alt":640,"title":640,"width":289,"height":641,"format":382,"focalPoint":642,"customData":643},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752676423-configure-email-zapier.jpg","Configure email Zapier",1798,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":645,"listStyle":374,"darkTheme":11,"buttons":646,"color":370,"indent":11},"\u003Cp>Let’s see in details what we added:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Cstrong>To:\u003C\u002Fstrong> is the destination of the message, it contains  the recipient of the gift card.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Subject:\u003C\u002Fstrong> the subject of the message.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Body type:\u003C\u002Fstrong> we chose HTML.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Body:\u003C\u002Fstrong> we used the placeholder variables available from the previous step to populate the body of the message (in our case, the original message defined in the gift card creation page, the code of the gift card, and finally the activation link, that contains the internal ID of the gift card to be activated — we’ll go back on this in a short while, when we will build the callback for the activation link).\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Also here you can hit \u003Cem>Continue\u003C\u002Fem> and test with the test data. If everything goes well you should get an email in your inbox!\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":648,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":649,"alt":650,"title":650,"width":289,"height":651,"format":382,"focalPoint":652,"customData":653},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752676894-notification-email.jpg","Notification email from Zapier",579,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":655,"listStyle":374,"darkTheme":11,"buttons":656,"color":370,"indent":11},"\u003Ch4>Implementing the activation link\u003C\u002Fh4>\n\n\u003Cp>We now need to implementation of the activation link. We are going to use Zapier for this part as well. Let’s publish the zap we worked on so far and create a new one that we’ll call &quot;Gift Card Activation&quot;:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":658,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":659,"alt":660,"title":660,"width":256,"height":661,"format":382,"focalPoint":662,"customData":663},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752677176-hook-setup-zapier.jpg","Hook setup Zapier",314,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":665,"listStyle":374,"darkTheme":11,"buttons":666,"color":370,"indent":11},"\u003Cp>The trigger in this case will be the \u003Ca href=\"https:\u002F\u002Fzapier.com\u002Fapps\u002Fwebhook\u002Fintegrations\">Webhook by Zapier\u003C\u002Fa> app, that will expose an endpoint that will trigger the execution pipeline:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":668,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":669,"alt":670,"title":670,"width":589,"height":671,"format":382,"focalPoint":672,"customData":673},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752679189-hook-configure-zapier.jpg","Hook configure Zapier",304,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":675,"listStyle":374,"darkTheme":11,"buttons":676,"color":370,"indent":11},"\u003Ch4>Activating the gift card\u003C\u002Fh4>\n\n\u003Cp>The last step is close the pipeline by using again the Commerce Layer Zapier app and specify as the event \u003Cem>Activate Gift Card\u003C\u002Fem>:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":678,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":679,"alt":680,"title":680,"width":589,"height":681,"format":382,"focalPoint":682,"customData":683},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752678881-activate-gift-card-setup-zapier.jpg","Activate gift card setup Zapier",452,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":685,"listStyle":374,"darkTheme":11,"buttons":686,"color":370,"indent":11},"\u003Cp>The activation action requires the ID of the gift card to be activated. We’ll be passing it as a query string parameter to the URL we generated before:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":688,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":689,"alt":690,"title":690,"width":589,"height":691,"format":382,"focalPoint":692,"customData":693},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752679092-activate-gift-card-configure-zapier.jpg","Activate gift card configure Zapier",270,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":695,"listStyle":374,"darkTheme":11,"buttons":696,"color":370,"indent":11},"\u003Cp>You can now save and publish the zap. If everything works correctly, when customers hit the activation link in the email they should be presented with something similar to the screenshot below:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":698,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":699,"alt":700,"title":700,"width":701,"height":702,"format":382,"focalPoint":703,"customData":704},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752679845-hook-response-zapier.jpg","Hook response zapier",989,305,{"x":292,"y":292},{},{"_modelApiKey":367,"icon":706,"copy":707,"color":370},"lightbulb","\u003Cp>Of course, this is not ideal for a production solution, but it’s just to give you a proof of concept. For example, instead of using Zapier, you can expose an endpoint on your web application that shows a nice confirmation page. There’s plenty of possibilities!\u003C\u002Fp>\n",{"_modelApiKey":372,"copy":709,"listStyle":374,"darkTheme":11,"buttons":710,"color":370,"indent":11},"\u003Cp>But let’s see what happened to our gift card in the Dashboard:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"border":7,"caption":280,"image":712,"size":385,"darkTheme":11,"rounded":7,"color":370},{"url":713,"alt":714,"title":714,"width":289,"height":715,"format":382,"focalPoint":716,"customData":717},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1752679613-gift-card-activated-dashboard.jpg","Gift card activated dashboard",669,{"x":292,"y":292},{},{"_modelApiKey":372,"copy":719,"listStyle":374,"darkTheme":11,"buttons":720,"color":370,"indent":11},"\u003Cp>The gift card is now active and can be used as a payment method!\u003C\u002Fp>\n\n\u003Ch3>Conclusion\u003C\u002Fh3>\n\n\u003Cp>In this tutorial, we walked through the full lifecycle of a Commerce Layer gift card — from personalization and creation to purchase and activation. We integrated Commerce Layer’s APIs and React components into a simple Next.js app, using the hosted checkout for payment and Zapier for automating the activation flow.\u003C\u002Fp>\n\n\u003Cp>While the implementation presented is simplified for demonstration purposes, it provides a solid foundation for building a real-world gift card experience. By combining Commerce Layer’s robust ecommerce backend with flexible frontend tools and third-party automation platforms, developers can deliver personalized, scalable, and automated gifting solutions.\u003C\u002Fp>\n\n\u003Cp>Whether you plan to enhance the design, manage activation internally, or support more advanced use cases like scheduling and rechargeability, the core concepts remain the same — \u003Cstrong>clean API integration, smart token handling, and event-driven workflows.\u003C\u002Fstrong>\u003C\u002Fp>\n\n\u003Cp>Happy coding — and happy gifting!\u003C\u002Fp>\n",[],[722,723,725,727,729,731,733,735,737,739,741,743,745,747,749,751,753],{"attributes":303,"tag":304,"content":305},{"attributes":724,"tag":309,"content":303},{"property":308,"content":305},{"attributes":726,"tag":309,"content":303},{"name":312,"content":305},{"attributes":728,"tag":309,"content":303},{"name":315,"content":316},{"attributes":730,"tag":309,"content":303},{"property":319,"content":316},{"attributes":732,"tag":309,"content":303},{"name":322,"content":316},{"attributes":734,"tag":309,"content":303},{"property":325,"content":326},{"attributes":736,"tag":309,"content":303},{"property":329,"content":330},{"attributes":738,"tag":309,"content":303},{"property":333,"content":334},{"attributes":740,"tag":309,"content":303},{"name":337,"content":326},{"attributes":742,"tag":309,"content":303},{"property":340,"content":341},{"attributes":744,"tag":309,"content":303},{"property":344,"content":345},{"attributes":746,"tag":309,"content":303},{"property":348,"content":349},{"attributes":748,"tag":309,"content":303},{"property":352,"content":353},{"attributes":750,"tag":309,"content":303},{"property":356,"content":280},{"attributes":752,"tag":309,"content":303},{"name":359,"content":360},{"attributes":754,"tag":309,"content":303},{"name":363,"content":364},[756],{"name":285,"picture":757},{"url":287,"alt":288,"title":288,"width":289,"height":289,"format":290,"focalPoint":758,"customData":759},{"x":292,"y":292},{},1790593730332]