{"id":27868,"date":"2021-07-27T20:01:05","date_gmt":"2021-07-27T20:01:05","guid":{"rendered":"http:\/\/Using-Shoppable-Video-in-Next.js"},"modified":"2021-07-27T20:01:05","modified_gmt":"2021-07-27T20:01:05","slug":"using-shoppable-video-in-next-js","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/","title":{"rendered":"Using Shoppable Video in Next.js"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>YouTube, Twitch, and TikTok are some of the most used platforms to promote and advertise products. <a href=\"https:\/\/blog.hubspot.com\/marketing\/video-marketing\">According to Blog Hubspot<\/a>, consumers prefer videos to images because videos give a better overview of the product.<\/p>\n<p>Shoppable Video is an e-commerce feature by Cloudinary that allows users to add \u201cshoppable\u201d items in their product videos. This feature will enable customers to shop while watching your videos. The customers can shop the items that are then added to the cart. They will be redirected to a page to make a purchase when done shopping.<\/p>\n<p>In this article, we will learn how we can render Shoppable videos in a NextJS app.<\/p>\n<p>You can learn more on <a href=\"https:\/\/cloudinary.com\/documentation\/video_player_shoppable_videos\">Shoppable video from the Cloudinary documentation<\/a>.<\/p>\n<p>This Shoppable Video feature is included in Cloudinary\u2019s video package. Therefore, we can use the Cloudinary package to add the Shoppable Video feature to our videos. We will also learn how to render data of any selected item in the shoppable video\u2019s product bar.<\/p>\n<p>To demonstrate this, we will build a Next.js web app. This app will render the product videos on an index page. We will have a product details page, and this page will open to display a product when it\u2019s clicked on the product bar.<\/p>\n<p>On the product details page, the product\u2019s name, price, image are shown, and an <code>Add to Cart<\/code> button to add the product to our shopping basket.<\/p>\n<p>Our final app will look like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_4C615933F31D4DC8B94A8055C19EA461A59CEA7A8BCB9BDD63B4F20545D8697E_1625404816531_shoppable.gif\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"480\" height=\"393\"\/><\/p>\n<h2>Sandbox<\/h2>\n<p>The entire project was completed on <a href=\"https:\/\/codesandbox.io\/s\/crimson-frog-ywsso\">CodeSand<\/a><a href=\"https:\/\/codesandbox.io\/s\/crimson-frog-ywsso\">b<\/a><a href=\"https:\/\/codesandbox.io\/s\/crimson-frog-ywsso\">ox<\/a>. Fork it to run the code.<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">    \n<\/code><\/span><\/pre>\n<\/div>\n  \n  <div class=\"wp-block-cloudinary-code-sandbox \">\n    <iframe\n      src=\"https:\/\/codesandbox.io\/embed\/crimson-frog-ywsso?theme=dark&amp;codemirror=1&amp;highlights=&amp;editorsize=50&amp;fontsize=14&amp;expanddevtools=0&amp;hidedevtools=0&amp;eslint=0&amp;forcerefresh=0&amp;hidenavigation=0&amp;initialpath=%2F&amp;module=&amp;moduleview=0&amp;previewwindow=&amp;view=&amp;runonclick=1\"\n      height=\"500\"\n      style=\"width: 100%;\"\n      title=\"Using Shoppable video in Nextjs\"\n      loading=\"lazy\"\n      allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n      sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n    ><\/iframe>\n  <\/div>\n\n  <div class=\"wp-block-cloudinary-markdown \"><pre class=\"js-syntax-highlighted\"><code>\nGitHub URL: https:\/\/github.com\/nextjs-prj\/cloudinary-shoppable\n\n## Prerequisites &amp; Installation\n\nThe knowledge of JavaScript and React.js is required for this project. We require a Node.js binary and NPM, its package manager installed.  \n\nTo create a new Next.js app, we open the terminal in our desired directory and run the below command:\n\n```bash\n    yarn create next-app nextjs-shop\n    # OR\n    npx create-next-app nextjs-shop\n<\/code><\/pre>\n<p>Alternatively, you can create a Next.js project using <a href=\"https:\/\/yarnpkg.com\/\">yarn<\/a>, as seen above.<\/p>\n<p>This command will create a <code>Next<\/code> app in the <code>nextjs-shop<\/code> directory. We move into the directory with the command <code>cd nextjs-shop<\/code>.<\/p>\n<p>The Shoppable Video feature was built by Cloudinary; therefore, to add the feature to our app, we have to install Cloudinary\u2019s SDK and its dependencies, which include the following:<\/p>\n<ul>\n<li>\n<a href=\"https:\/\/www.npmjs.com\/package\/lodash\">lodash<\/a> : Contains major utility functions for Nodejs.<\/li>\n<li>\n<a href=\"https:\/\/www.npmjs.com\/package\/cloudinary-core\">cloudinary-core<\/a>: Cloudinary JavaScript library that provides Cloudinary\u2019 APIs and administration capabilities to web development.<\/li>\n<li>\n<a href=\"https:\/\/www.npmjs.com\/package\/cloudinary-video-player\">cloudinary-video-player<\/a>: The Cloudinary Video Player is a JavaScript-based HTML5 video player bundled with many valuable customization and integration capabilities and is monetization and analytics-ready.<\/li>\n<\/ul>\n<p>We will reference the lodash library, Cloudinary core and the Cloudinary video player directly from the <a href=\"https:\/\/unpkg.com\/\">Unpkg CDN<\/a>.<\/p>\n<p>In the root directory of the project, open <code>_app.js<\/code> and update the returned JSX elements in the  <code>&lt;Head&gt;..&lt;\/Head&gt;<\/code> section to include:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>Create Next App<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"description\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"Generated by create next app\"<\/span> \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"icon\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/favicon.ico\"<\/span> \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span>\n              <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"https:\/\/unpkg.com\/cloudinary-video-player@1.5.3\/dist\/cld-video-player.min.css\"<\/span>\n              <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"stylesheet\"<\/span>\n            \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>\n              <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/unpkg.com\/cloudinary-core@latest\/cloudinary-core-shrinkwrap.min.js\"<\/span>\n              <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\/javascript\"<\/span>\n            &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>\n              <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/unpkg.com\/cloudinary-video-player@1.5.3\/dist\/cld-video-player.min.js\"<\/span>\n              <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\/javascript\"<\/span>\n            &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n    \/\/...\n<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>This will load all the libraries once the app starts, and <code>cloudinary<\/code> is available to all components through the <code>window<\/code> object.<\/p>\n<h2>Rendering Shoppable Videos<\/h2>\n<p>We will create our page route files. Then, the already existing <code>index.js<\/code> in the <code>pages<\/code> folder will render the index page.<\/p>\n<p>So we create the pages using the terminal command in the project\u2019s <code>pages<\/code> directory:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">    mkdir product\n    touch product\/&#91;id].js\n    \n    mkdir cart\n    touch cart\/index.js\n<\/code><\/span><\/pre>\n<p>The <code>product\/[id].js<\/code> is a dynamic page. It takes the id of each component in its <code>[id]<\/code>. The <code>cart\/index.js<\/code> is the page that lists the cart.<\/p>\n<h2>Setup a cart provider<\/h2>\n<p>In <code>_app.js<\/code>, we will set up a cart provider using React\u2019s Context API. Then, we will persist products added to our cart using localStorage.\nWe will have methods <code>getCart<\/code>, <code>removeFromCart<\/code> and <code>addToCart<\/code>. The Context Provider will pass around these methods, and components will consume them via the <code>useContext<\/code> hook. To do this, first, we import all required dependencies using:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">\"..\/styles\/globals.css\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> Header <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/Header\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> Head <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/head\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> React, { useCallback } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n    \n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> CartContext = React.createContext(<span class=\"hljs-literal\">null<\/span>);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Then, we create a <code>MyApp<\/code> component with functions to get, add, and remove an item from cart:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">MyApp<\/span>(<span class=\"hljs-params\">{ Component, pageProps }<\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> getCart = useCallback(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        <span class=\"hljs-keyword\">const<\/span> state = <span class=\"hljs-built_in\">window<\/span>.localStorage.getItem(<span class=\"hljs-string\">\"state\"<\/span>);\n        <span class=\"hljs-keyword\">if<\/span> (state) {\n          <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-built_in\">JSON<\/span>.parse(state);\n        }\n        <span class=\"hljs-keyword\">return<\/span> &#91;];\n      });\n    \n      <span class=\"hljs-keyword\">const<\/span> addToCart = useCallback(<span class=\"hljs-function\">(<span class=\"hljs-params\">product<\/span>) =&gt;<\/span> {\n        <span class=\"hljs-keyword\">const<\/span> state = <span class=\"hljs-built_in\">window<\/span>.localStorage.getItem(<span class=\"hljs-string\">\"state\"<\/span>);\n        <span class=\"hljs-keyword\">if<\/span> (state) {\n          <span class=\"hljs-keyword\">const<\/span> stateObj = <span class=\"hljs-built_in\">JSON<\/span>.parse(state);\n          stateObj.push(product);\n          <span class=\"hljs-built_in\">window<\/span>.localStorage.setItem(<span class=\"hljs-string\">\"state\"<\/span>, <span class=\"hljs-built_in\">JSON<\/span>.stringify(stateObj));\n        } <span class=\"hljs-keyword\">else<\/span> {\n          <span class=\"hljs-keyword\">const<\/span> stateObj = &#91;product];\n          <span class=\"hljs-built_in\">window<\/span>.localStorage.setItem(<span class=\"hljs-string\">\"state\"<\/span>, <span class=\"hljs-built_in\">JSON<\/span>.stringify(stateObj));\n        }\n        <span class=\"hljs-built_in\">window<\/span>.location.reload();\n      });\n    \n      <span class=\"hljs-keyword\">const<\/span> removeFromCart = useCallback(<span class=\"hljs-function\">(<span class=\"hljs-params\">product<\/span>) =&gt;<\/span> {\n        <span class=\"hljs-keyword\">const<\/span> state = <span class=\"hljs-built_in\">window<\/span>.localStorage.getItem(<span class=\"hljs-string\">\"state\"<\/span>);\n        <span class=\"hljs-keyword\">const<\/span> stateObj = <span class=\"hljs-built_in\">JSON<\/span>.parse(state);\n        <span class=\"hljs-keyword\">const<\/span> remProducts = stateObj.filter(<span class=\"hljs-function\">(<span class=\"hljs-params\">_prduct<\/span>) =&gt;<\/span> _prduct.id != product?.id);\n        <span class=\"hljs-built_in\">window<\/span>.localStorage.setItem(<span class=\"hljs-string\">\"state\"<\/span>, <span class=\"hljs-built_in\">JSON<\/span>.stringify(remProducts));\n        <span class=\"hljs-built_in\">window<\/span>.location.reload();\n      });\n    \n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n          \n        <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n      );\n    }\n    \n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> MyApp;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We created a <code>CartContext<\/code> by calling the <code>React.createContext<\/code> API.\nFinally, we return the JSX component:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">MyApp<\/span>(<span class=\"hljs-params\">{ Component, pageProps }<\/span>) <\/span>{\n      <span class=\"hljs-comment\">\/\/ &#91;component methods go in here]<\/span>\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>Create Next App<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"description\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"Generated by create next app\"<\/span> \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"icon\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/favicon.ico\"<\/span> \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span>\n              <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"https:\/\/unpkg.com\/cloudinary-video-player@1.5.3\/dist\/cld-video-player.min.css\"<\/span>\n              <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"stylesheet\"<\/span>\n            \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>\n              <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/unpkg.com\/cloudinary-core@latest\/cloudinary-core-shrinkwrap.min.js\"<\/span>\n              <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\/javascript\"<\/span>\n            &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>\n              <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/unpkg.com\/cloudinary-video-player@1.5.3\/dist\/cld-video-player.min.js\"<\/span>\n              <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\/javascript\"<\/span>\n            &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n    \n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Header<\/span> \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CartContext.Provider<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">getCart<\/span>, <span class=\"hljs-attr\">addToCart<\/span>, <span class=\"hljs-attr\">removeFromCart<\/span> }}&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Component<\/span> {<span class=\"hljs-attr\">...pageProps<\/span>} \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">CartContext.Provider<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n      );\n    }\n    \n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> MyApp;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Here the <code>Header<\/code> component is rendered before the <code>Component<\/code>. This was done so that the <code>Header<\/code> will appear on all pages.<\/p>\n<p><code>Component<\/code> is the component being rendered in a route. We enclosed the <code>Component<\/code> with the <code>CartContext.Provider<\/code> passing in an object to its <code>value<\/code> attribute. The object contains the methods <code>getCart<\/code>, <code>removeFromCart<\/code> and <code>addToCart<\/code>.<\/p>\n<h2>Creating a site header<\/h2>\n<p>We create a file to contain a Header component using the terminal command:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">    mkdir components components\/Header\n    touch components\/Header\/index.js touch components\/Header\/Header.module.css\n<\/code><\/span><\/pre>\n<p>We updated the content in <code>components\/Header\/index.js<\/code> to:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> { header, headerName } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/Header.module.css\"<\/span>;\n    \n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Header<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{header}<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{headerName}<\/span>&gt;<\/span>Shopify<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span><\/span>\n      );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>It renders \u201cShopify\u201d, the name of our app.<\/p>\n<h2>Render product videos<\/h2>\n<p>We will proceed to create a Cloudinary instance and render our product videos.\nIn <code>pages\/index.js<\/code>, we first import all dependencies with:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">    import Head from \"next\/head\";\n    import styles from \"..\/styles\/Home.module.css\";\n    import Header from \"..\/components\/Header\";\n    import { ProductCard } from \"..\/components\/ProductCard\";\n    import { useContext, useEffect, useState } from \"react\";\n    import { CartContext } from \".\/_app\";\n    import Link from \"next\/link\";\n\nNext, we created a Home component with:\n\n```jsx\n    export default function Home() {\n      const &#91;cld, setCld] = useState();\n      const &#91;cart, setCart] = useState(&#91;]);\n      const { getCart } = useContext(CartContext);\n    \n      useEffect(() =&gt; {\n        if (cloudinary) {\n          const _cld = cloudinary.Cloudinary.new({ cloud_name: \"demo\" });\n          setCld(_cld);\n          setCart(getCart());\n        }\n      }, &#91;]);\n    \n      return (\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.container}<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>Shopify<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"description\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"Generated by create next app\"<\/span> \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"icon\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/favicon.ico\"<\/span> \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n    \n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.main}<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.breadcrumb}<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>Shopify Products<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    \n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.productscontainer}<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.yourproducts}<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span>&gt;<\/span>Product Videos<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Link<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/cart\"<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>\n                      <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span>\n                        <span class=\"hljs-attr\">cursor:<\/span> \"<span class=\"hljs-attr\">pointer<\/span>\",\n                        <span class=\"hljs-attr\">textDecoration:<\/span> \"<span class=\"hljs-attr\">underline<\/span>\",\n                        <span class=\"hljs-attr\">color:<\/span> \"<span class=\"hljs-attr\">blue<\/span>\",\n                      }}\n                    &gt;<\/span>\n                      Cart: <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>{cart?.length}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Link<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                {cld &amp;&amp;\n                  &#91;\"rafting\", \"sea_turtle\", \"forest_bike\"].map((product, i) =&gt; (\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ProductCard<\/span> <span class=\"hljs-attr\">cld<\/span>=<span class=\"hljs-string\">{cld}<\/span> <span class=\"hljs-attr\">product<\/span>=<span class=\"hljs-string\">{product}<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{i}<\/span> \/&gt;<\/span>\n                  ))}\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the <code>useEffect<\/code> hook, we got the <code>cloudinary<\/code> object and created a <code>Cloudinary<\/code> instance.<\/p>\n<p>The <code>cloud_name<\/code> passed to the <code>Cloudinary.new(..)<\/code> call is a unique indentifier for our Cloudinary account.<\/p>\n<blockquote>\n<p>To obtain a cloud name, <a href=\"https:\/\/cloudinary.com\/signup\">create a Cloudinary account for free<\/a>. The cloud name is visible on your Cloudinary dashboard.<\/p>\n<\/blockquote>\n<p><code>_cld<\/code> is an instance of the <code>Cloudinary<\/code> class. With this, we can call different methods and properties on the <code>Cloudinary<\/code> object.\nWe added the product videos name in an array and rendered the <code>ProductCard<\/code> component for each. The <code>ProductCard<\/code> is passed the <code>cld<\/code> instance and the product video name via similarly named props.<\/p>\n<p>Before we create the <code>ProductCard<\/code> component, we have to set up the shoppable configuration.<\/p>\n<p>We have product videos <code>forest_bike<\/code>, <code>sea_turtle<\/code> and <code>rafting<\/code>. We will set a shoppable configuration in the <code>data<\/code> directory of the project that will be passed to the Cloudinary player when initializing the videos.\nHere is the configuration for the rafting product video in this GitHub Gist:<\/p>\n<p><a href=\"https:\/\/gist.github.com\/Chuloo\/5db54cf58a83f2dd4c65bd7a134817a1\">https:\/\/gist.github.com\/Chuloo\/5db54cf58a83f2dd4c65bd7a134817a1<\/a><\/p>\n<p>The <code>products<\/code> array in the <code>shoppable<\/code> object holds the shoppable config for all the products in the <code>rafting<\/code> product video.<\/p>\n<p>This snippet sets the raft in the video as a product in the products bar. Here\u2019s a description of each key:<\/p>\n<ul>\n<li>The <code>productId<\/code> is the ID of the product.<\/li>\n<li>The <code>productName<\/code> is the name of the product. It is set to <code>Raft<\/code>.<\/li>\n<li>The <code>startTime<\/code> is the time the raft appears in the video. The unit is in milliseconds.<\/li>\n<li>The <code>endTime<\/code> is the time the raft product no longer appears in the video.<\/li>\n<li>The <code>publicId<\/code> is the ID of the product image. The ID can be the id of the image in our Cloudinary account, or the id can be a public image URL.<\/li>\n<li>The <code>hotspots<\/code> hold places in the video where we can add hotspots. The viewers can click on them for more info on the product.<\/li>\n<\/ul>\n<p>Let\u2019s see the object in the <code>hotspots<\/code> array:<\/p>\n<ul>\n<li>\n<code>time<\/code>: the exact time to display the hotspot.<\/li>\n<li>\n<code>x<\/code>: The position of the hotspot on the x-axis.<\/li>\n<li>\n<code>y<\/code>: The position of the hotspot on the y-axis.<\/li>\n<li>\n<code>tooltipPosition<\/code>: This is the alignment of the hotspot. The text can be aligned from either the left or from the right.<\/li>\n<li>Finally, <code>clickUrl<\/code>: This is the URL to visit when the URL is clicked.<\/li>\n<li>The <code>onClick<\/code> sets the click-behaviour of the product in the products bar.<\/li>\n<li>The <code>action<\/code> is the action to perform when clicked. It is set to <code>goto<\/code>, which will load a URL in a separate tab.<\/li>\n<li>The <code>args<\/code> object sets the argument passed to the <code>goto<\/code> action.<\/li>\n<li>The <code>url<\/code> sets the URL to go to when the product is clicked. Here, we put it to the dynamic route <code>product\/[id]<\/code> with the <code>id<\/code> being <code>raft<\/code>.<\/li>\n<\/ul>\n<p>Similarly, we have Shoppable configuration objects for both the <a href=\"https:\/\/gist.github.com\/Chuloo\/4a603d5bdb5e344f30af7e87729507b2\">sea_turtle<\/a> and <a href=\"https:\/\/gist.github.com\/Chuloo\/a8edda55fc8242a5a20942ff840e42ea\">forest_bike<\/a> product videos.<\/p>\n<h2>Create the Product Card component<\/h2>\n<p>This component renders each product video. We create new files for the component and its CSS modules using the terminal command:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">    mkdir components\/ProductCard\n    touch components\/ProductCard\/index.js \n    touch components\/ProductCard\/ProductCard.module.css\n<\/code><\/span><\/pre>\n<p>Next, we edit <code>ProductCard\/index.js<\/code> to:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> { useEffect, useRef } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> styles <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/ProductCard.module.css\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> data <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/..\/..\/data\"<\/span>;\n    \n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">ProductCard<\/span>(<span class=\"hljs-params\">{ cld, product }<\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> videoRef = useRef(<span class=\"hljs-literal\">null<\/span>);\n      useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        <span class=\"hljs-keyword\">const<\/span> source = data&#91;product];\n        <span class=\"hljs-keyword\">const<\/span> demoplayer = cld.videoPlayer(videoRef.current).width(<span class=\"hljs-number\">850<\/span>);\n        demoplayer.source(product, source);\n      });\n    \n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.productcard}<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">video<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"500\"<\/span> <span class=\"hljs-attr\">ref<\/span>=<span class=\"hljs-string\">{videoRef}<\/span> <span class=\"hljs-attr\">controls<\/span> <span class=\"hljs-attr\">muted<\/span> <span class=\"hljs-attr\">preload<\/span>=<span class=\"hljs-string\">\"false\"<\/span>&gt;<\/span>\n            {\" \"}\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">video<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n      );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Here we destructured <code>cld<\/code> and <code>product<\/code> from the props passed which are the Cloudinary instance, and the name of the Cloudinary\u2019s video to render, respectively.<\/p>\n<p>In the <code>useEffect<\/code> hook we set the shoppable config from the <code>product<\/code> passed. Then we called the <code>videoPlayer()<\/code> method from the <code>cld<\/code> Cloudinary instance. This <code>videoPlayer()<\/code> method is passed the reference to a <code>video<\/code> element. This action makes Cloudinary sets its features on the <code>video<\/code> HTMLElement. We passed <code>videoRef.current<\/code> to the method. This holds a reference to the <code>video<\/code> element in our UI.\nThe <code>width<\/code> method sets the width of the <code>video<\/code> element. The third line of code calls the <code>source<\/code> method in the <code>demoPlayer<\/code>. This <code>demoPlayer<\/code> holds a reference to the <code>video<\/code> element. We passed the <code>product<\/code> to the <code>source<\/code> method as the first argument and the <code>source<\/code> as the second argument. The <code>source<\/code> has the shoppable configuration of each video.<\/p>\n<p>With this, we have configured and rendered shoppable videos in a Nextjs app.<\/p>\n<p>Next, we\u2019ll scaffold other components.<\/p>\n<h2>Create the cart card components<\/h2>\n<p>This component will render each product card in the cart. We create the component file and CSS module using the terminal command:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">    mkdir components\/CartCard\n    touch components\/CartCard\/index.js touch components\/CartCard\/CartCard.module.css\n<\/code><\/span><\/pre>\n<p>We update <code>CartCard\/index.js<\/code> to:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> styles <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/CartCard.module.css\"<\/span>;\n    \n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">CartCard<\/span>(<span class=\"hljs-params\">{ cart }<\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> { name, imageUrl, price } = cart;\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.cartcard}<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>\n            <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">backgroundImage:<\/span> `<span class=\"hljs-attr\">url<\/span>(${<span class=\"hljs-attr\">imageUrl<\/span>})` }}\n            <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.cartcardimg}<\/span>\n          &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.cartcarddetails}<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.cartcardname}<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span>&gt;<\/span>{name}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.cartcardprice}<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>{price}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n      );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Here, we destructured the <code>cart<\/code> object from the component props. Then, we render the name, the price and the image URL of the product.<\/p>\n<h2>Collecting data from Shoppable video selection<\/h2>\n<p>We already configured each product in the product bars of each video to load the route <code>product\/[id]<\/code>. So the <code>id<\/code> is the name of the product. For example, <code>product\/raft<\/code>, id becomes <code>raft<\/code>.\nIn <code>data\/product_data.js<\/code> we create product data that will hold the price, name, and the image URL of each shoppable product.<\/p>\n<p>You can find it in this GitHub Gist below.<\/p>\n<p><a href=\"https:\/\/gist.github.com\/Chuloo\/3809aae48de401ae193ea1c5f47904d4\">https:\/\/gist.github.com\/Chuloo\/3809aae48de401ae193ea1c5f47904d4<\/a><\/p>\n<p><a href=\"https:\/\/gist.github.com\/Chuloo\/3809aae48de401ae193ea1c5f47904d4\">https:\/\/gist.github.com\/Chuloo\/3809aae48de401ae193ea1c5f47904d<\/a><\/p>\n<p>Each object in the <code>data<\/code> array has an <code>id<\/code> to hold the unique ID of the product, <code>name<\/code> to hold the name of the product, <code>imageUrl<\/code> to hold the image URL of the product, and the <code>price<\/code> to hold the price of the product.\nIn the <code>product\/[id].js<\/code> page component, we will extract the product\u2019s id from the <code>id<\/code> param, use it to get the product details from the <code>data<\/code> above, then render it.<\/p>\n<p>First, we imported all required dependencies, defined the component, and its methods:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> styles <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/..\/styles\/ProductView.module.css\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { useRouter } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/router\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> products_data <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/..\/..\/data\/products_data\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { useEffect, useState, useContext } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { CartContext } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/..\/_app\"<\/span>;\n    \n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Product<\/span>(<span class=\"hljs-params\">params<\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> { getCart, removeFromCart, addToCart } = useContext(CartContext);\n      <span class=\"hljs-keyword\">const<\/span> &#91;inCart, setInCart] = useState(<span class=\"hljs-literal\">false<\/span>);\n    \n      <span class=\"hljs-keyword\">const<\/span> router = useRouter();\n      <span class=\"hljs-keyword\">const<\/span> {\n        <span class=\"hljs-attr\">query<\/span>: { id },\n      } = router;\n      <span class=\"hljs-keyword\">const<\/span> product = products_data.find(<span class=\"hljs-function\">(<span class=\"hljs-params\">_product<\/span>) =&gt;<\/span> _product.id == id);\n    \n      useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        <span class=\"hljs-keyword\">const<\/span> cart = getCart();\n        <span class=\"hljs-keyword\">const<\/span> _cartFound = cart.find(<span class=\"hljs-function\">(<span class=\"hljs-params\">_prdct<\/span>) =&gt;<\/span> _prdct.id == id);\n        <span class=\"hljs-keyword\">const<\/span> inCart = _cartFound ? <span class=\"hljs-literal\">true<\/span> : <span class=\"hljs-literal\">false<\/span>;\n        setInCart(inCart);\n      });\n    \n      <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">_addToCart<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n        addToCart(product);\n      }\n    \n      <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">_removeFromCart<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n        removeFromCart(product);\n      }\n    \n      <span class=\"hljs-keyword\">return<\/span> (\n        \n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We got the value of the <code>CartContext<\/code> using the <code>useContext<\/code> hook. The state <code>inCart<\/code> is a boolean to hold a <code>true<\/code> value if the product is already in the shopping cart, and <code>false<\/code> if otherwise.\nNext, we extracted the <code>id<\/code> of the product from the params using the <code>useRouter<\/code> hook. Finally, we get the details of the product from the <code>data<\/code> object and then render it on the UI.\nThe <code>useEffect<\/code> callback checks the cart to know if the product has been in the cart and then sets the <code>inCart<\/code> state appropriately.<\/p>\n<p>The <code>_addToCart<\/code> and <code>_removeFromCart<\/code> functions all call the <code>addToCart<\/code> and <code>removeFromCart<\/code> functions in the <code>CartContext<\/code>.<\/p>\n<p>Next we render the JSX elements with:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Product<\/span>(<span class=\"hljs-params\">params<\/span>) <\/span>{\n    <span class=\"hljs-comment\">\/\/ component definitions go in here<\/span>\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.productviewcontainer}<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.productviewmain}<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>\n              <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">backgroundImage:<\/span> `<span class=\"hljs-attr\">url<\/span>(${<span class=\"hljs-attr\">product<\/span>?<span class=\"hljs-attr\">.imageUrl<\/span>})` }}\n              <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.productviewimg}<\/span>\n            &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">width:<\/span> \"<span class=\"hljs-attr\">100<\/span>%\", <span class=\"hljs-attr\">marginLeft:<\/span> \"<span class=\"hljs-attr\">15px<\/span>\" }}&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.productviewname}<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>{product?.name}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.productviewminidet}<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>\n                  <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span>\n                    <span class=\"hljs-attr\">borderTop:<\/span> \"<span class=\"hljs-attr\">1px<\/span> <span class=\"hljs-attr\">solid<\/span> <span class=\"hljs-attr\">black<\/span>\",\n                    <span class=\"hljs-attr\">borderBottom:<\/span> \"<span class=\"hljs-attr\">1px<\/span> <span class=\"hljs-attr\">solid<\/span> <span class=\"hljs-attr\">black<\/span>\",\n                    <span class=\"hljs-attr\">paddingTop:<\/span> \"<span class=\"hljs-attr\">18px<\/span>\",\n                    <span class=\"hljs-attr\">paddingBottom:<\/span> \"<span class=\"hljs-attr\">18px<\/span>\",\n                  }}\n                &gt;<\/span>\n                  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>\n                    <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span>\n                      <span class=\"hljs-attr\">marginRight:<\/span> \"<span class=\"hljs-attr\">4px<\/span>\",\n                      <span class=\"hljs-attr\">color:<\/span> \"<span class=\"hljs-attr\">rgb<\/span>(<span class=\"hljs-attr\">142<\/span> <span class=\"hljs-attr\">142<\/span> <span class=\"hljs-attr\">142<\/span>)\",\n                      <span class=\"hljs-attr\">display:<\/span> \"<span class=\"hljs-attr\">flex<\/span>\",\n                      <span class=\"hljs-attr\">alignItems:<\/span> \"<span class=\"hljs-attr\">center<\/span>\",\n                    }}\n                  &gt;<\/span>\n                    Price:{\"  \"}\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">color:<\/span> \"<span class=\"hljs-attr\">black<\/span>\", <span class=\"hljs-attr\">fontSize:<\/span> \"<span class=\"hljs-attr\">2em<\/span>\" }}&gt;<\/span>\n                      {product?.price}\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">padding:<\/span> \"<span class=\"hljs-attr\">14px<\/span> <span class=\"hljs-attr\">0<\/span>\" }}&gt;<\/span>\n                  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                    {!inCart ? (\n                      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"btn\"<\/span> <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{_addToCart}<\/span>&gt;<\/span>\n                        Add to Cart\n                      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n                    ) : (\n                      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"btn-danger\"<\/span> <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{_removeFromCart}<\/span>&gt;<\/span>\n                        Remove from Cart\n                      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n                    )}\n                  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n      );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We used the <code>inCart<\/code> value to conditionally render either an <code>Add to Cart<\/code> or <code>Remove from Cart<\/code> button.<\/p>\n<h2>Create the Cart page<\/h2>\n<p>This page will render all the products in our cart. In a new <code>index.js<\/code> file in the <code>pages\/cart<\/code> directory, we add the cart page component with:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> styles <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/..\/..\/styles\/Home.module.css\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { CartContext } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/..\/_app\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { useContext, useEffect, useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> CartCard <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/..\/..\/components\/CartCard\"<\/span>;\n    \n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Cart<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> { getCart } = useContext(CartContext);\n      <span class=\"hljs-keyword\">const<\/span> &#91;cart, setCart] = useState(&#91;]);\n    \n      useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        <span class=\"hljs-keyword\">const<\/span> cart = getCart();\n        setCart(cart);\n      });\n    \n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.container}<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.main}<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.breadcrumb}<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>Cart<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n                  <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"btn\"<\/span>\n                  <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">backgroundColor:<\/span> \"<span class=\"hljs-attr\">green<\/span>\", <span class=\"hljs-attr\">borderColor:<\/span> \"<span class=\"hljs-attr\">green<\/span>\" }}\n                &gt;<\/span>\n                  Checkout\n                <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    \n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.productscontainer}<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                {cart.map((_cartItem, i) =&gt; (\n                  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CartCard<\/span> <span class=\"hljs-attr\">cart<\/span>=<span class=\"hljs-string\">{_cartItem}<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{i}<\/span> \/&gt;<\/span>\n                ))}\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n      );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Here, we got the <code>getCart<\/code> function from the <code>CartContext<\/code> using the <code>useContext<\/code> hook.\nThe <code>cart<\/code> state is an array that holds the products in our cart. In the <code>useEffect<\/code> hook, the <code>getCart<\/code> function gets called, and the result is added to the <code>cart<\/code> state. The <code>cart<\/code> is then rendered using the <code>map<\/code> function.\nFinally, each cart item is rendered with the <code>CartCard<\/code> component.<\/p>\n<h2>Conclusion<\/h2>\n<p>Shoppable Videos add interactivity to your product videos. This increases purchases and store conversion.\nIn this tutorial, we started by introducing and learning about Shoppable videos. We demonstrated how to render them in a Nextjs app. Finally, we built a live Next.js store to demo the usage.<\/p>\n<p>Head over to the <a href=\"https:\/\/cloudinary.com\/documentation\/video_player_shoppable_videos#defining_products\">Shoppable Video docs<\/a> to learn more. You can find the source code of the project <a href=\"https:\/\/github.com\/nextjs-prj\/cloudinary-shoppable\">here<\/a>.<\/p>\n<h2>Resources<\/h2>\n<p>You may find the following resources useful.<\/p>\n<ul>\n<li>\n<a href=\"https:\/\/cloudinary.com\/documentation\/video_player_shoppable_videos\">Shoppable videos<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/github.com\/css-modules\/css-modules\">CSS Modules<\/a>\n<\/li>\n<\/ul>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":27869,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,212,382,371,303],"class_list":["post-27868","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-next-js","tag-player-video","tag-under-review","tag-video"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Using Shoppable Video in Next.js<\/title>\n<meta name=\"description\" content=\"Boost e-commerce conversion using shoppable videos. Learn to utilize a shoppable video in Next.js\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using Shoppable Video in Next.js\" \/>\n<meta property=\"og:description\" content=\"Boost e-commerce conversion using shoppable videos. Learn to utilize a shoppable video in Next.js\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2021-07-27T20:01:05+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926041\/Web_Assets\/blog\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3.jpg?_i=AA\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Using Shoppable Video in Next.js\",\"datePublished\":\"2021-07-27T20:01:05+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/\"},\"wordCount\":6,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926041\/Web_Assets\/blog\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3.jpg?_i=AA\",\"keywords\":[\"Guest Post\",\"Next.js\",\"Player Video\",\"Under Review\",\"Video\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2021\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/\",\"name\":\"Using Shoppable Video in Next.js\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926041\/Web_Assets\/blog\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3.jpg?_i=AA\",\"datePublished\":\"2021-07-27T20:01:05+00:00\",\"description\":\"Boost e-commerce conversion using shoppable videos. Learn to utilize a shoppable video in Next.js\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926041\/Web_Assets\/blog\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926041\/Web_Assets\/blog\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3.jpg?_i=AA\",\"width\":5760,\"height\":3840},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using Shoppable Video in Next.js\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Using Shoppable Video in Next.js","description":"Boost e-commerce conversion using shoppable videos. Learn to utilize a shoppable video in Next.js","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/","og_locale":"en_US","og_type":"article","og_title":"Using Shoppable Video in Next.js","og_description":"Boost e-commerce conversion using shoppable videos. Learn to utilize a shoppable video in Next.js","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/","og_site_name":"Cloudinary Blog","article_published_time":"2021-07-27T20:01:05+00:00","twitter_card":"summary_large_image","twitter_image":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926041\/Web_Assets\/blog\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3.jpg?_i=AA","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/"},"author":{"name":"","@id":""},"headline":"Using Shoppable Video in Next.js","datePublished":"2021-07-27T20:01:05+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/"},"wordCount":6,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926041\/Web_Assets\/blog\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3.jpg?_i=AA","keywords":["Guest Post","Next.js","Player Video","Under Review","Video"],"inLanguage":"en-US","copyrightYear":"2021","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/","name":"Using Shoppable Video in Next.js","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926041\/Web_Assets\/blog\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3.jpg?_i=AA","datePublished":"2021-07-27T20:01:05+00:00","description":"Boost e-commerce conversion using shoppable videos. Learn to utilize a shoppable video in Next.js","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926041\/Web_Assets\/blog\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926041\/Web_Assets\/blog\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3.jpg?_i=AA","width":5760,"height":3840},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/using-shoppable-video-in-next-js\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Using Shoppable Video in Next.js"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926041\/Web_Assets\/blog\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3\/74cb741a7abd8650d25253c933cf2f29ab720c51-5760x3840-1_2786911de3.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/27868","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=27868"}],"version-history":[{"count":0,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/27868\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/27869"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=27868"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=27868"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=27868"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}