Cloudinary Blog

Integrating Video in Custom Shopify Apps

By Marcelo Ricardo de Oliveira
Integrating Video in Customer Shopify Apps

Although bringing products to life with high-quality video started as a nice-to-have feature, video has become a key part of e-commerce. Consumers expect to see product videos before making purchasing decisions, especially since the COVID-19 pandemic has prevented them from browsing products in person, significantly expanding the e-commerce market.

Oftentimes, once they discover the convenience of shopping online, many consumers stop patronizing brick-and-mortar stores.

This article shows web developers how to create a custom Shopify app and then perform two tasks for a superior user experience (UX):

Integrate Cloudinary Into Your Shopify Store
Already have a Shopify store and are looking how to better optimize your page with Cloudinary? Check out the below resources to start optimizing your performance budget.

Enhancing a Shopify Store With Apps

To add features to Shopify stores, start with building web apps called Shopify apps, which seamlessly integrate with the Shopify platform. Even though they leverage the power of that platform, you can host those apps in your own infrastructure or somewhere else. Shopify offers extensive documentation on the procedures for developing Shopify apps in the most relevant programming languages. Also, depending on your purpose and your client’s needs, you can choose from several different types of Shopify apps: public, custom, private, etc.

However, custom apps have limitations, especially if you plan to expand their audience someday. Because you tailor them for specific retailers, you can't sell custom apps in the Shopify App Store. Nor can you charge clients with the Shopify’s Billing API for using your custom apps.

Nonetheless, if the standard apps don’t offer the tools you need or don’t help your client’s store stand out, a custom app is the way to go. For example, even though Shopify supports video out of the box, that platform limits video size. Such a restriction and other factors might pose too much constraint for your needs.

In contrast, Cloudinary enhances e-commerce UX by serving optimized videos tailored to the visitor’s device. Additionally, the UX offered by Cloudinary’s Product Gallery widget outshines Shopify’s default by far. Once you’ve learned how to create custom apps, as described below, you’ll be well on your way to mastering the techniques of building advanced, video-based Shopify apps.

Creating a Node.js App

To integrate Cloudinary into Shopify, first create a Shopify app based on Node.js, React, and Next.js. The Shopify App CLI is a superb command-line interface for efficiently creating, installing, and launching Shopify apps by quickly scaffolding Node.js and Ruby on Rails apps, automating many everyday development tasks.

For the procedure on how to create a custom Shopify app, see this section in the Shopify documentation: Getting started with Shopify App CLI.

Uploading Product Media to Cloudinary

After creating a Node.js custom app, add a product video. For an overview of how Cloudinary works and integrates with websites and apps, read the related documentation.

You can upload videos to Cloudinary in either of these two ways:

  • With the upload widget — By using Cloudinary's interactive, feature-rich, and simple-to-integrate upload widget, you can upload media directly to Cloudinary, saving you the hassle of developing an in-house tool for interactive uploads.
  • With a direct call to the REST API — To enable you to perform tasks beyond the upload widget’s capabilities, Cloudinary's client libraries (SDKs) wrap the upload API, greatly simplifying the use of the API methods (see the upload API reference documentation for details). Nevertheless, to upload files with a direct call to the API from within your custom code, simply send an HTTPS POST request to a Cloudinary URL.

I recommend uploading media to your Cloudinary Media Library with the upload widget for its user-friendly user interface (UI).

Leveraging Your Cloudinary Credentials

Do the following:

  1. Sign up for a free Cloudinary account and log in to access the Cloudinary management console's dashboard for your account details. Note your account's Cloud name, which you'll use later in the custom Shopify app.

    Account details

  2. Click Settings at the top of the Cloudinary management console and, under Upload presets, ensure that the mode reads Unsigned:

    Account settings

  3. Open your custom app’s root directory and, in a text editor of your choice, update the .env file by adding the values of your account’s cloud name and upload preset, like this:

    Copy to clipboard
    SHOPIFY_API_KEY="YOUR_SHOPIFY_API_KEY"
    SHOPIFY_API_SECRET="YOUR_SHOPIFY_SECRET"
    HOST="YOUR_TUNNEL_URL"
    SHOP="YOUR-SHOP-NAME.myshopify.com"
    SCOPES=write_products,write_customers,write_draft_orders
    CLOUDINARY_CLOUD_NAME="YOUR_CLOUDINARY_CLOUD_NAME"
    CLOUDINARY_UPLOAD_PRESET="YOUR_CLOUDINARY_UPLOAD_PRESET"
  4. Open the next.config.js file and add the values of your account’s cloud name and upload preset, like this:

Copy to clipboard
const withCSS = require("@zeit/next-css");

const webpack = require("webpack");
const apiKey = JSON.stringify(process.env.SHOPIFY_API_KEY);
const cloudinaryCloudName = process.env.CLOUDINARY_CLOUD_NAME;
const cloudinaryUploadPreset = process.env.CLOUDINARY_UPLOAD_PRESET;

module.exports = withCSS({
  webpack: config => {
    const env = { API_KEY: apiKey };
    const env = {
      API_KEY: apiKey
    };
    config.plugins.push(new webpack.DefinePlugin(env));
    return config;
  },
  publicRuntimeConfig: {
    staticFolder: '/static',
    cloudinaryCloudName: cloudinaryCloudName,
    cloudinaryUploadPreset: cloudinaryUploadPreset
  }
});

Implementing the Product Gallery Widget

Next, follow these steps:

1. Open the index.js file in the pages folder and add the JavaScript link required by Cloudinary’s upload widget:

Copy to clipboard
const Index = () => (
  <div>
    <Page>
      <script src="https://widget.cloudinary.com/v2.0/global/all.js" type="text/javascript"></script>
    </Page>
  </div>
)

2. Add a React component to list the products and enable uploading of media by creating a folder called components and a file there named ProductList.js with this code:

Copy to clipboard
import {
  Card,
  ResourceList,
  Stack,
  TextStyle,
  Thumbnail,
} from '@shopify/polaris';

  const ResourceListWithProducts = () => {

    return (
      <Card>
        <ResourceList
          showHeader
          resourceName={{ singular: 'Product', plural: 'Products' }}
          renderItem={item => {

            return (
              <ResourceList.Item>
                <Stack>
                  <Stack.Item fill>
                      <TextStyle variation="strong">

                      </TextStyle>
                  </Stack.Item>
                </Stack>
              </ResourceList.Item>
            );
          }}
        />
      </Card>
    );
  }

export default ResourceListWithProducts;

Note
Later on, you’ll list your client’s products in your Shopify app with the ResourceListWithProducts React component. You’re also importing the Card, ResourceList, Stack, TextStyle, and Thumbnail React components from Shopify’s Polaris design system.

3. Obtain the store’s product list with a query through Shopify’s GraphQL API. Start with importing the gql template so that you can write a GraphQL query that is parsed into a standard GraphQL abstract syntax tree:

Copy to clipboard
import gql from 'graphql-tag';

4. Declare a GET_PRODUCTS GraphQL query with the gql template:

Copy to clipboard
const GET_PRODUCTS = gql`
{
  products(first: 100) {
    edges {
      node {
        id
        handle
        title
        images(first:1) {
          edges {
            node {
              id
              originalSrc
            }
          }
        }
        variants(first: 1) {
          edges {
            node {
              id
              displayName
            }
          }
        }
      }
    }
  }
}
`;

Afterwards, import the Query component from the react-apollo package to render the results returned by the GraphQL query above:

Copy to clipboard
import { Query } from 'react-apollo';

5. Modify the return of the ResourceListWithProducts function so that the Query component can render its results:

Copy to clipboard
const ResourceListWithProducts = () => {

  return (
    <Query query={GET_PRODUCTS}>
      {({ data, loading, error }) => {
        if (loading) return <div>Loading…</div>;
        if (error) return <div>{error.message}</div>;

        return (
          <Card>
            <ResourceList
              showHeader
              resourceName={{ singular: 'Product', plural: 'Products' }}
              items={data.products.edges}
              renderItem={item => {
                const media = item.node.images.edges.length > 0
                ? (<Thumbnail source={item.node.images.edges[0].node.originalSrc}/>)
                : (<Thumbnail source=''/>);

                return (
                  <ResourceList.Item
                    id={item.node.id}
                    media={media}>
                    <Stack>
                      <Stack.Item fill>
                          <TextStyle variation="strong">
                            {item.node.title}
                          </TextStyle>
                      </Stack.Item>
                    </Stack>
                  </ResourceList.Item>
                );
              }}
            />
          </Card>
        );
      }}
    </Query>)
}

export default ResourceListWithProducts;

6. Obtain your Cloudinary credentials from your app and import the getConfig function from Next.js:

Copy to clipboard
import getConfig from 'next/config';

Afterwards, obtain the publicRuntimeConfig function from the getConfig function:

Copy to clipboard
const { publicRuntimeConfig } = getConfig();

7. Add a function named uploadMediaClick to the ResourceListWithProducts component:

Copy to clipboard
const ResourceListWithProducts = () => {

  const uploadMediaClick = (productId) => {

    const productIdNumber = productId.split('/')[productId.split('/').length - 1];

    var myWidget = cloudinary.createUploadWidget({
      cloudName: publicRuntimeConfig.cloudinaryCloudName,
      upload_preset: publicRuntimeConfig.cloudinaryUploadPreset,
      showAdvancedOptions: true
    }, (error, result) => { if (result.event == "success") {

      console.log(result.info);
  } })

  myWidget.update({tags: [productIdNumber]});
  myWidget.open();
}

8. Modify the list details by adding a button followed by an upload of product-related media:

Copy to clipboard
<ResourceList.Item
  id={item.node.id}
  media={media}>
  <Stack>
    <Stack.Item fill>
        <TextStyle variation="strong">
          {item.node.title}
        </TextStyle>
    </Stack.Item>
    <Stack.Item>
      <button 
      name="upload_widget" 
      className="cloudinary-button"
      onClick={uploadMediaClick.bind(this, item.node.id)}>Upload media</button>
    </Stack.Item>
  </Stack>
</ResourceList.Item>

Note that the button’s click event calls the uploadMediaClick function you created earlier.

Using the ProductList Component

Proceed with these steps to make use of the ProductList component:

1. Open the index.js file under the pages folder again and import the ProductList component you just created:

Copy to clipboard
import ProductList from '../components/ProductList';

2. Add the ProductList component to the index page:

Copy to clipboard
const Index = () => (
  <div>
    <Page>
      <ProductList />
      <script src="https://widget.cloudinary.com/v2.0/global/all.js" type="text/javascript"></script>
    </Page>
  </div>
)

3. Compile and install your app on the development store with Shopify’s serve command:

Copy to clipboard
...\YOUR-APP-DIRECTORY> shopify serve

The Shopify CLI now compiles and launches your custom app locally:

Copy to clipboard
√ ngrok tunnel running at https://XXXXXXXXXXXX.ngrok.io, with account your@email.com
√ .env saved to project root
? Do you want to update your application url? (You chose: yes)
√ Whitelist URLS updated in Partners Dashboard

* To install and start using your app, open this URL in your browser:
https://XXXXXXXXXXXX.ngrok.io/auth?shop=cloudinaryapp.myshopify.com

┏━━ Running server... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃ 
┃ > shopify-app-node@1.0.0 dev YOUR-APP-DIRECTORY
┃ > cross-env NODE_ENV=development nodemon ./server/index.js --watch ./server/index.js
┃ 
┃ [nodemon] 2.0.6
┃ [nodemon] to restart at any time, enter `rs`
┃ [nodemon] watching path(s): server\index.js
┃ [nodemon] watching extensions: js,mjs,json
┃ [nodemon] starting `node ./server/index.js`
┃ Loaded env from YOUR-APP-DIRECTORY\.env
┃ Warning: Built-in CSS support is being disabled due to custom CSS configuration being detected.
┃ See here for more info: https://err.sh/next.js/built-in-css-disabled
┃ 
┃ event - compiled successfully
┃ > Ready on http://localhost:8081

Note that the Shopify serve command generates this URL, which you can open in your browser to install and start using your app:

https://XXXXXXXXXXXX.ngrok.io/auth?shop=cloudinaryapp.myshopify.com

Alternatively, open another command-line console and type this command to start your app:

Copy to clipboard
...\YOUR-APP-DIRECTORY> shopify open

Shopify Cloudinary App

All Products

Next, follow the steps below to create two product entries on your Shopify admin website:

  • Ballet Dance Shoes
  • Short-Sleeve T-Shirt

Select Product

  1. Select both entries and choose Set as active from the More actions menu so that they appear in the store’s catalog.
  2. Click Ballet Dance Shoes for the product details. Note that the URL ends with the product ID 6065347199138. Product ID
  3. Next, click Apps on the left and select the name of your custom app (in this case CloudinaryApp) for a display of the two product entries you just added. Click Apps
  4. Click Upload media under Ballet Dance Shoes for the dialog box of Cloudinary’s upload widget. Upload Media
  5. Click Browse and select a few images and videos that relate to Ballet Dance Shoes. Browse Media The four media files above have already been uploaded to Cloudinary, each tagged with a Shopify product ID.
  6. Open your Cloudinary Dashboard to see those files. Media Library
  7. Open one of the files and verify that it’s tagged with 6065347199138, Shopify’s product ID for Ballet Dance Shoes. Product Tag
  8. Click the eye icon to the right of the Online Store to open your store’s website. View Online Store Online Store
  9. Click the Catalog link at the top of the home page: Catalog
  10. Click Ballet Dance Shoes for its details page. Ballet Dance Shoes

No related media is displayed. Edit a few Shopify templates to show the product images and videos, as in this sample Shopify website: Sample site

Modifying the Theme for Your Shopify Store

Since the Shopify platform knows nothing about your Media Library on Cloudinary, you must modify a Shopify theme file, e.g., the one called Debut, to store your Cloudinary credentials and leverage the Cloudinary Product Gallery. Follow these steps:

  1. Open your Shopify admin dashboard and click Themes. Themes
  2. Click Explore free themes under Free themes, select the Debut theme, and add it to your theme library: Free themes
  3. Pull down the Actions menu to the right of the Debut name and choose Publish. Debut

Adding Cloudinary Settings to Your Shopify Installation

Next, download from Cloudinary this ZIP file, which contains all the code changes you must make for Shopify's Debut theme. Cloudinary offers a collection of such files, from which you can conveniently copy and paste Cloudinary-specific code into your own themes.

To apply changes to the Debut theme:

  1. Log in to your Shopify admin console, navigate to Online Store > Themes and choose Actions > Edit code for the theme you want to change. Theme Library
  2. Select the settings_schema.json file in the Config folder and then, from settings_schema.json in the ZIP file, copy and paste to the file the block with "name": "Cloudinary". Config
  3. Under Snippets, click Add a new snippet and name it cloudinary.liquid. Copy and paste to the snippet the entire content of cloudinary.liquid in the ZIP file. Snippet
  4. Select theme.liquid under the Layout folder. From theme.liquid in the ZIP file, copy and paste the code to add Cloudinary’s JavaScript files. Layout
  5. Select product-card-grid.liquid under the Snippets folder. From product-card-grid.liquid in the ZIP file, copy and paste the entire block to the snippet, starting from the comment “This whole block is to get Cloudinary urls.” Snipets
  6. Select the settings_data.json file under the Config folder. From settings_data.json in the ZIP file, copy and paste to the file the Cloudinary settings at the top and replace shopify-demo with your cloud name. Config
  7. Navigate to Online Store > Themes and choose Actions > Edit in the online store for the theme you just changed. You'll see Cloudinary under Theme Settings. Theme settings
  8. In the Cloudinary settings dialog box, configure whether to enable asset delivery from Cloudinary. Alternatively, specify a different cloud and change your delivery URL to the corresponding one. Dialog box

The same ZIP file you used in the previous section includes the code for integration with Cloudinary's Product Gallery. Your goal is to replace Shopify’s product gallery with Cloudinary’s on each of the product pages.

Once you’ve completed the edits, Cloudinary automatically adds to each product gallery all the media, tagged with the related product IDs, from the configured Cloudinary account. You need not upload those assets to Shopify—a tremendous convenience! Note, however, that the order of images is important in galleries; be sure to verify it's correct.

Do the following:

  1. Go back to the code editor and select product-template.liquid in the Sections folder. From product-template.liquid in the ZIP file, copy and paste the code from the comment "Cloudinary product gallery" to "Cloudinary changes end.” Sections
  2. Select theme.scss.liquid in the Assets folder. From theme.scss.liquid in the ZIP file, copy and paste the CSS in the comments that start with /* Cloudinary changes. Assets
  3. By default, Cloudinary’s Product Gallery cannot access your media files. To grant that access, navigate to your management console's dashboard on Cloudinary, click the Settings icon (⚙), click the Security tab, and deselect Resource List under Restricted media types. Settings
  4. Now open your Shopify admin dashboard, go to Products, and select Ballet Dance Shoes for the details. Magically, displayed in the gallery are the images and videos you’ve associated with the product, as in this example: Product image

Moving on to the Next Steps

You just learned how easy it is to integrate video into a custom Shopify app with the Cloudinary and Shopify APIs. And, you're just getting started.

Consider the huge volume of transformations you can apply with Cloudinary's API after uploading a video but before making it visible on a Shopify product page. Cloudinary covers almost all the video-integration scenarios you’ll likely encounter as an e-commerce developer and works with major e-commerce platforms like Magento and BigCommerce.

With Shopify apps, you can offer e-commerce clients robust and effective administration features. For details on how to properly integrate apps with APIs, see GraphQL Admin API reference and Shopify REST Admin API reference.

Additionally, you can configure Cloudinary Product Gallery in many ways. Watch this demo and then try out some of the customization options yourself.

Cloudinary’s video tools help distinguish your Shopify app and your client’s store from the crowd, complete with a superior UX for customers and store owners alike. Again, to incorporate Cloudinary’s video tools into your app, first register for a free account.

About the Author

Marcelo Ricardo de Oliveira is a senior freelance software developer who lives with his lovely wife, Luciana, and his little buddy and stepson, Kauê, in Guarulhos, Brazil. He cofounded the Brazilian TV Guide and currently works for Alura Cursos Online.

Integrate Cloudinary Into Your Shopify Store
Already have a Shopify store and are looking how to better optimize your page with Cloudinary? Check out the below resources to start optimizing your performance budget.

Recent Blog Posts

Our $2B Valuation

By
Blackstone Growth Invests in Cloudinary

When we started our journey in 2012, we were looking to improve our lives as developers by making it easier for us to handle the arduous tasks of handling images and videos in our code. That initial line of developer code has evolved into a full suite of media experience solutions driven by a mission that gradually revealed itself over the course of the past 10 years: help companies unleash the full potential of their media to create the most engaging visual experiences.

Read more
Direct-to-Consumer E-Commerce Requires Compelling Visual Experiences

When brands like you adopt a direct–to-consumer (DTC) e-commerce approach with no involvement of retailers or marketplaces, you gain direct and timely insight into evolving shopping behaviors. Accordingly, you can accommodate shoppers’ preferences by continually adjusting your product offering and interspersing the shopping journey with moments of excitement and intrigue. Opportunities abound for you to cultivate engaging customer relationships.

Read more
Automatically Translating Videos for an International Audience

No matter your business focus—public service, B2B integration, recruitment—multimedia, in particular video, is remarkably effective in communicating with the audience. Before, making video accessible to diverse viewers involved tasks galore, such as eliciting the service of production studios to manually dub, transcribe, and add subtitles. Those operations were costly and slow, especially for globally destined content.

Read more
Cloudinary Helps Minted Manage Its Image-Generation Pipeline at Scale

Shoppers return time and again to Minted’s global online community of independent artists and designers because they know they can count on unique, statement-making products of the highest quality there. Concurrently, the visual imagery on Minted.com must do justice to the designs into which the creators have poured their hearts and souls. For Minted’s VP of Engineering David Lien, “Because we are a premium brand, we need to ensure that every single one of our product images matches the selected configuration exactly. For example, if you pick an 18x24 art print on blue canvas, we will show that exact combination on the hero images in the PDF.”

Read more
Highlights on ImageCon 2021 and a Preview of ImageCon 2022

New year, same trend! Visual media will continue to play a monumental role in driving online conversions. To keep up with visual-experience trends and best practices, Cloudinary holds an annual conference called ImageCon, a one-of-a-kind event that helps attendees create the most engaging visual experiences possible.

Read more