Creating shoppable video with Cloudinary, BigCommerce, and Uniform

Introduction

Shoppable videos, which keep visitors at e-commerce stores engaged, are a great way to enhance the purchasing experience and boost sales. This tutorial steps you through the process of creating a shoppable video with Cloudinary, BigCommerce, and Uniform.

Discerning the technologies

Cloudinary is an image-and video-management service through which you can upload, optimize, transform, and deliver media assets on the web.
BigCommerce is an e-commerce platform for selling both physical and digital merchandise.
Uniform offers digital-experience composition features with which you can create, deliver, and manage building blocks for apps. Instead of making multiple API requests, you can employ Jamstack technologies, such as headless CMSes, commerce APIs, and CDNs, delivering digital experiences as a single source of truth.

Leveraging StackBlitz and GitHub

You’ll work through this tutorial in StackBlitz. Fork it over with this codeline:
1<iframe src="https://stackblitz.com/edit/github-anehxu?embed=1&file=app.vue"></iframe
The source code is available on GitHub.

Understanding the prerequisites

This tutorial requires —

Getting started

  1. Create a Next.js project by running this command in your terminal:
    1npx create-next-app uniform-shoppabl
  2. Navigate to the project directory and run the application:
    1cd uniform-shoppabl
  3. Install the Uniform and Cloudinary libraries you’ll need later:
    1npm i cloudinary-video-player @uniformdev/canvas @uniformdev/canvas-bigcommerce @uniformdev/canvas-cloudinary @uniformdev/canvas-reac
  4. Run this command to start the application:
    1npm run de

Uploading video to Cloudinary

Upload this video to your Cloudinary account by clicking the Media Library tab at the top of your Cloudinary account’s dashboard and uploading the video to a folder of your choice.

Configuring BigCommerce

Uploading product data to BigCommerce
Your new BigCommerce account comes with dummy product data. For this tutorial, update the inventory with three products of your choice:
Product Name
Default Price
Weight
Product 1
450
2
Product 2
270
2
Product 3
270
2
To do that, click Add in the Products menu on the sidebar, input the product name, default price, and weight for each of the three products in the appropriate text fields. Click Save.
BigCommerce - Navigate to the page for adding products
BigCommerce - Add products
Creating an API account
Create an API account through which third-party applications can access your products. Follow the steps below:
  1. In the main menu, click Settings, scroll to the API section, and click API accounts.
    BigCommerce - Navigate to the main menu
    BigCommerce - Click an API account
  2. Click Create API Account and type the account name in the appropriate text field.
  3. Scroll down to the Products section and set API permissions to read-only.
    BigCommerce - Products section
  4. Create an .env file in the root of the Next.js application and add the store hash and BigCommerce API token to that file.
    1BIGCOMMERCE_STORE_HASH=your-store-hash-here
    2BIGCOMMERCE_API_TOKEN=your-token-here
    For the value of the store hash, look under API path for the string after https://api.bigcommerce.com/store. Copy and paste that string after BIGCOMMERCE_STORE_HASH=Click to copy in the .envClick to copy file.
    BigCommerce - Create Account
  5. Click Save. A dialog box with the access token and other credentials then pops up.
  6. Copy the access token and paste it under BIGCOMMERCE_API_TOKEN=Click to copy in the .envClick to copy file.
BigCommerce - Access Token

Integrating BigCommerce and Cloudinary into Uniform and configuring the Uniform project

Uniform supports the integration of several third-party services, including BigCommerce and Cloudinary, for the creation of captivating digital experiences. So, integrate the product data on BigCommerce and the video on Cloudinary into Uniform, as follows:
  1. Log in to your Uniform account, click Create New Project at the top and name the project uniform-shoppableClick to copy. Click Continue.
    Creating a new Uniform component
  2. Add the product to the Uniform project: Click the Products tab and then the product. Click the Integrations tab at the top.
    Click on the project
    Click the Integrations tab
  3. Next, click BigCommerce under Browse Integrations and then the Add to project button. Input the store hash and API token you added to the .envClick to copy file earlier in the appropriate text fields. Click Save.
    Select BigCommerce integration
    Add an integration
    Input credentials
  4. Follow the same steps to add the Cloudinary integration: Input your Cloudinary account’s cloudnameClick to copy and API key and then click Save.
    Add Cloudinary credentials
    The values of your cloudnameClick to copy and API key are displayed in your Cloudinary account’s dashboard.
    Cloudinary account details
Finally, create a Uniform API key:
  1. Click the Security tab and then the + icon. Type uniform-shoppableClick to copy as the API name, click Add to Project, select all the permissions, and click Set Permissions. Click Create API Key.
    Create API key
    Set permissions
    Uniform then displays the API key under Key and the project ID under Projects.
    Copy generated API key and project ID
  2. Update the .envClick to copy file with those credentials:
    1  UNIFORM_API_KEY=your-api-key-here
    2  UNIFORM_PROJECT_ID=your-project-id-here

Creating the Uniform Components

A Uniform composition is a group of reusable building blocks that carry properties, just as React components do.
For this tutorial, create four components:
  • Page, on which to mount other components.
  • ShoppableVideo, in which to hold the Cloudinary video.
  • Chapter, the chapter you’ll define for the Cloudinary Video Player.
  • Hotspot, the hotspot you’ll define for the Cloudinary Video Player.
Do the following:
  1. Click the Canvas tab, followed by Component Library and the + icon, and then name the components appropriately.
    Create a component
    Name the component
    Since Page is a composition component, select the Composition Component setting.
    Set Page as a composition component
  2. Define the slots: Click a component and then the Slots tab and the + icon. Select the appropriate component for each slot:
    • The ShoppableVideo component is a slot of the Page component.
    • The Chapter component is a slot of the ShoppableVideo component.
    • The Hotspot component is a slot of the Chapter component.
      Create a slot
      Set the appropriate slot
  3. Define the parameters for the components: Click each of the components and then Parameters. Add the component properties as shown in the tables below the screenshot. Click OK.
    Adding the parameters
    Fill in the parameters’ values

ShoppableVideo

Parameter Name
Type
CTA
Text
Cloudinary
Cloudinary

Chapter

Parameter Name
Type
Chapter Title
Cloudinary
Product
BigCommerce Product
Start Time
Number
End Time
Number
Click Action
Dropdown List

Hotspot

Parameter Name
Type
Time
Cloudinary
X Position
Number
Y Position
Number
tooltipPosition
Dropdown List

Creating the Uniform Compositions

Next, create the compositions for the components you created.
  1. In the Canvas tab, lick Compositions and then the + icon. Select Page as the component type, name the composition Shopping, and click Create.
    Create a Uniform composition
  2. Type /Click to copy under Slug.
    Fill in the slug
  3. Specify the compositions for the ShoppableVideo, Chapter, and Hotspot components.
    ShoppableVideo’s composition
    Chapter’s composition
    Hotspot’s composition
  4. Select Publish from the Save dropdown menu.
    Publish and save composition
  5. Click the Canvas tab and then the Publish button to make your composition available to third-party applications.
    Click publish

Integrating Uniform with Next.js

Now integrate Uniform into your Next.js application.

Creating the VideoPlayer Component

To enable the VideoPlayercomponentClick to copy to hold the Cloudinary Video Player, create a components/VideoPlayer.jsClick to copy file with the code below.
1import "cloudinary-video-player/dist/cld-video-player.min.js";
2import "cloudinary-video-player/dist/cld-video-player.min.css";
3import { useEffect } from "react";
1export default function VideoPlayer = ({ cloudname, cta, video, products }) => {
2  useEffect(() => {
3    const videoPlayer = cloudinary.videoPlayer("shoppable-video-player", {
4      cloud_name: cloudname,
5      muted: true,
6      controls: true,
7      fluid: true,
8    });
9    var source = {
10      shoppable: {
11        startState: "openOnPlay",
12        bannerMsg: cta,
13        showPostPlayOverlay: true,
14        products,
15      },
16    };
17    if (products.length > 0) {
18      videoPlayer.source(video, source);
19    } else {
20      videoPlayer.source(video);
21    }
22  }, [video, products, cloudname, cta]);
23  return (
24    <div>
25      <video
26        id="shoppable-video-player"
27        className="cld-video-player cld-video-player-skin-light"
28      />
29    </div>
30  );
31};
The above code performs two tasks:
  1. Import the required dependencies.
  2. Configure the Cloudinary Video Player and ensure that the products exist before adding the source for the shoppable feature.

Creating the Resolve renderer

The resolver maps through the Uniform data and passes it to ShoppableVideoClick to copy. To make that happen, set up resolveRendererClick to copy, which you passed to the CompositionClick to copy component, by creating a components/ResolveRenderer.jsClick to copy file with the code below.
1import { DefaultNotImplementedComponent } from "@uniformdev/canvas-react";
2import ShoppableVideo from "./ShoppableVideo";
3const mappings = {
4  shoppablevideo: ShoppableVideo,
5};
6export function resolveRenderer(component) {
7  const componentImpl = mappings[component.type];
8  return componentImpl ? componentImpl : DefaultNotImplementedComponent;
9}
10export default mappings;
The above code performs two tasks:
  1. Import the required dependencies.
  2. Map through the shoppableVideoClick to copy data from Uniform and pass it to the ShoppableVideoClick to copy component.

Creating the ShoppableVideo component

Next, define the data that enables the functions of Cloudinary’s shoppable video. Create a components/ShoppableVideo.jsClick to copy file with the code below.
1import dynamic from "next/dynamic";
2import format from "format-duration";
1export default function ShoppableVideo({ component }) {
2  const DynamicVideo = dynamic(() => import("./VideoPlayer"), {
3    ssr: false,
4  });
5  const cta = component.parameters.cta.value;
6  const { publicId } = component.parameters.cloudinary.value[0];
7  const cloudname = your-cloud-name;
8  let products = [];
9  
10  if (component.slots?.chapters) {
11    products = component.slots.chapters.map((chapter) => {
12      const { id, name, price, image } = chapter.parameters.product.value;
13      const clickAction = { args: {} };
14      if (chapter.parameters.clickAction.value === "goToProduct") {
15        clickAction.action = "goto";
16        clickAction.pause = true;
17        clickAction.args.url = `https://uniform-shoppable.mybigcommerce.com/${name}`;
18      } else {
19        clickAction.action = "seek";
20        clickAction.pause = true;
21        clickAction.args.time = format(
22          1000 * chapter.parameters.startTime.value,
23          { leading: true }
24        );
25      }
26      const hotspots = [];
27      if (chapter?.slots?.hotspots) {
28        const { time, tooltipposition, x, y } =
29          chapter.slots.hotspots[0].parameters;
30        hotspots.push({
31          time: format(1000 * time.value, { leading: true }),
32          x: `${x.value}%`,
33          y: `${y.value}%`,
34          tooltipPosition: tooltipposition.value,
35          clickUrl: `https://uniform-shoppable.mybigcommerce.com/${name}`,
36        });
37      }
38      const result = {
39        productId: id,
40        productName: `${name} - $${price}`,
41        startTime: Number(chapter.parameters.startTime.value),
42        endTime: Number(chapter.parameters.endTime.value),
43        publicId: image,
44        onClick: clickAction,
45      };
46      if (hotspots.length > 0) {
47        result.hotspots = hotspots;
48      }
49      return result;
50    });
51  }
52  const options = { video: publicId, cta, cloudname, products };
53  return (
54    <>
55      <DynamicVideo {...options} />
56    </>
57  );
58}
The above code does the following:
  1. Import the required documents.
  2. Dynamically import the VideoPlayerClick to copy component.
  3. Retrieve the ctaClick to copy and publicIdClick to copy parameters from the component and define the value of cloudnameClick to copy, which you obtained from your Cloudinary account’s dashboard earlier.
  4. Check whether the chaptersClick to copy slot exists in ShoppableVideoClick to copy and, if so, perform these tasks:
    1. Map through the chapters and extract the values for idClick to copy, nameClick to copy, priceClick to copy, and imageClick to copy.
    2. Define the click action of the shoppable video’s products and execute the gotoClick to copy or seekClick to copy action, depending on the value of the clickActionClick to copy parameter.
    3. Check whether the hotspotsClick to copy slot exists and, if so, configure the hotspots. Also verify that the length of the hotspotsClick to copy array is greater than 0.
    4. Configure and return a resultClick to copy object with information on each of the BigCommerce products.
  5. Set up an optionsClick to copy object to hold the configuration you’ll pass to Cloudinary to activate the shoppable-video feature.

Add an enhancer

Since Uniform stores only the reference ID and not the data you input while creating compositions, adding an enhancer helps you make queries, pull data, and transform the data into a structured format for the frontend. 
Create an enhancers/index.jsClick to copy file with the code below.
1import { compose, EnhancerBuilder } from "@uniformdev/canvas";
2import {
3  CLOUDINARY_PARAMETER_TYPES,
4  cloudinaryEnhancer,
5} from "@uniformdev/canvas-cloudinary";
6import {
7  createBigCommerceClient,
8  createBigCommerceEnhancer,
9  CANVAS_BIGCOMMERCE_PARAMETER_TYPES,
10} from "@uniformdev/canvas-bigcommerce";
1export const bigCommerceClient = createBigCommerceClient({
2  storeHash: process.env.BIGCOMMERCE_STORE_HASH,
3  token: process.env.BIGCOMMERCE_API_TOKEN,
4});
1export const bigCommerceEnhancer = () =>
2  createBigCommerceEnhancer({
3    client: bigCommerceClient,
4    createProductOptions: () => {
5      return {
6        include_fields: ["id", "name", "price"],
7      };
8    },
9  });
10  
11export const bigCommerceModelCleaner = ({ parameter }) => {
12  const { id, name, images, price } = parameter.value;
13  parameter.value = {
14    id,
15    name,
16    price,
17    image: images[0].url_standard,
18  };
19  return parameter.value;
20};
1export const enhancers = new EnhancerBuilder()
2  .parameterType(CLOUDINARY_PARAMETER_TYPES, cloudinaryEnhancer)
3  .parameterType(
4    CANVAS_BIGCOMMERCE_PARAMETER_TYPES,
5    compose(bigCommerceEnhancer(), bigCommerceModelCleaner)
6  );
The above code does the following:
  1. Import the required dependencies.
  2. Create BigCommerceClientClick to copy with the store hash and API key you saved earlier.
  3. Created BigCommerceEnhancerClick to copy with the createBigCommerceEnhancerClick to copy method and then define the product fields (idClick to copy, nameClick to copy, and priceClick to copy) with the createProductOptionsClick to copy function.
  4. Set up the bigCommerceModelCleanerClick to copy function, which extracts the data from the products and returns them.
  5. Create a new instance of EnhancerBuilderClick to copy and pass to it the relevant parameters.

Getting composable data from Uniform

Update the pages/index.jsClick to copy file with the code below:
1import Head from "next/head";
2import { CanvasClient, enhance } from "@uniformdev/canvas";
3import { Composition, Slot } from "@uniformdev/canvas-react";
4import { enhancers } from "../enhancers";
5import { resolveRenderer } from "../components/ResolveRenderer";
1export default function IndexPage({ composition }) {
2  return (
3    <div>
4      <Head>
5        <title>Shoppable Video with Cloudinary, Uniform and BigCommerce</title>
6      </Head>
7      <Composition data={composition} resolveRenderer={resolveRenderer}>
8        <Slot name="components" />
9      </Composition>
10    </div>
11  );
12}
1export async function getStaticProps() {
2  const client = new CanvasClient({
3    apiKey: process.env.UNIFORM_API_KEY,
4    projectId: process.env.UNIFORM_PROJECT_ID,
5  });
6  const { composition } = await client.getCompositionBySlug({
7    slug: "/",
8  });
9  await enhance({
10    composition,
11    enhancers,
12    context: {},
13  });
14  return {
15    props: {
16      composition,
17    },
18  };
}
The above code does the following:
  1. Import the required dependencies.
  2. Fetch data from Uniform with the getStaticPropsClick to copy function, which also performs these three tasks:
    1. Create a CanvasClientClick to copy instance with the API key and project ID.
    2. Fetch compositionClick to copy through the getCompositionBySlugClick to copy method in the CanvasClientClick to copy instance.
    3. Render the data you fetched from Uniform with the CompositionClick to copy and SlotClick to copy components.
You’ve now created a shoppable video with Cloudinary, BigCommerce, and Uniform. Of significance is Uniform’s support of third-party integrations, which facilitates the creation of engaging digital experiences through a combination of Uniform and best-in-class technologies.
shoppable video final
Guides/Creating shoppable video with Cloudinary, BigCommerce, and Uniform