DEV Community

loading...
Cover image for Enhanced eCommerce in PWA Studio

Enhanced eCommerce in PWA Studio

jordaneisenburg profile image Jordan Eisenburger ・2 min read

This blog post is mainly aimed at Magento agencies building a mono-repo around PWA Studio and having a need to make an easy yet extensible way to add Enhanced eCommerce.

Note that if you don't have a mono repo setup like PWA Studio you won't need the React Context

Overview:

  • Adding Google Tag Manager
  • Creating a React Context
  • Setting up a basic data layer file
  • Implementing the data layer methods

Adding Google Tag Manager

Add the code below, make sure to add your own GTM code.
I'd advice you to make the GTM code variable so you can connect to multiple containers based on your build/pipeline etc.

//template.html (the inside your storefront)
<script>
    dataLayer = [];
</script>
<!-- Google Tag Manager -->
<script>
    (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
            new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer','GTM-XXXXXX');
</script>
<!-- End Google Tag Manager -->
Enter fullscreen mode Exit fullscreen mode

Creating a React Context

Since we are working inside a mono-repo we want to be able to customise what data we send to the data layer per customer that's build upon the mono-repo.

So firstly locate the position where you'd normally would create context's inside your project.

Add the following files:
context/dataLayer/index.js
context/dataLayer/dataLayer.js
context/dataLayer/data.js

//context/dataLayer/index.js
export { DataLayerProvider, useDataLayerConfig } from './dataLayer';
Enter fullscreen mode Exit fullscreen mode
//context/dataLayer/dataLayer.js

import React, { useContext } from 'react';
import { node, object } from 'prop-types';
import { merge } from 'lodash-es';
import { dataLayerConfig } from './data';

export const DataLayer = React.createContext(null);

const defaultDataLayer = dataLayerConfig;

export const DataLayerProvider = ({ children, additionalDataLayer = {} }) => {
    return (
        <DataLayer.Provider
            value={merge({}, defaultDataLayer, additionalDataLayer)}
        >
            {children}
        </DataLayer.Provider>
    );
};

export const useDataLayerConfig = () => useContext(DataLayer);

DataLayerProvider.propTypes = {
    children: node.isRequired,
    query: object,
    additionalDataLayer: object,
};

Enter fullscreen mode Exit fullscreen mode
//context/dataLayer/data.js
export const dataLayerConfig = {
    reset: {
        product: () => ({
            ecommerce: undefined,
            items: undefined,
        }),
        category: () => ({
            ecommerce: undefined,
            items: undefined,
        }),
    },
    product: data => ({
        event: 'virtualPageview',
        pagePath: window.location.href,
        pageTitle: `${data.name} - ${STORE_NAME}`,
        pageType: 'product',
        items: [
            {
                id: data.sku,
            },
        ],
        ecommerce: {
            detail: {
                products: [
                    {
                        name: data.name,
                        id: data.sku,
                    },
                ],
            },
        },
    }),
    cms: data => ({
        event: 'virtualPageview',
        pagePath: window.location.href,
        pageTitle: `${data.title} - ${STORE_NAME}`,
        pageType: 'cms',
    }),
    category: data => ({
        event: 'virtualPageview',
        pagePath: window.location.href,
        pageTitle: `${data.category.name} - ${STORE_NAME}`,
        pageType: 'category',
    }),
    removeFromCart: data => ({
        event: 'removeFromCart',
        ecommerce: {
            remove: {
                products: [
                    {
                        name: data.product.name,
                        id: data.product.sku,
                        quantity: data.quantity,
                    },
                ],
            },
        },
    }),
    addToCart: data => ({
        event: 'addToCart',
        items: [
            {
                id: data.sku,
            },
        ],
        ecommerce: {
            add: {
                products: [
                    {
                        name: data.name,
                        id: data.sku,
                        quantity: data.quantity,
                    },
                ],
            },
        },
    }),
};

Enter fullscreen mode Exit fullscreen mode

Note that this a really small example file, you should add more methods like submitOrder, checkoutSuccess, checkout, notFound etc etc

Make sure to import the Context into the storefront and add it to the provider tree.

//index.js (the on in your storefront)
<AppContextProvider>
  <DataLayerProvider>
    ...
  </DataLayerProvider>
</AppContextProvider>

Enter fullscreen mode Exit fullscreen mode

Implementing the data layer methods

So we've set up the basic of this solution

Discussion (0)

pic
Editor guide