DEV Community

Cover image for Enhanced eCommerce in PWA Studio
Jordan Eisenburger
Jordan Eisenburger

Posted on

Enhanced eCommerce in PWA Studio

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

Top comments (3)

Collapse
 
kossanah profile image
kossanah • Edited

@jordaneisenburg thanks for sharing your knowledge. can this be implemented with node GTM module github.com/alinemorelli/react-gtm

Collapse
 
mumtaz1000 profile image
mumtaz1000

I am very new to Pwa studio and working on applying google analytics in my pwa project and now kind of stuck and rely hoping to get some help!!!!

Collapse
 
sanganinamrata profile image
Namrata

@jordaneisenburg thank you so much for your blog. I'm stuck at at which place to put all the "//context/" files in PWA repo?