mParticle ProductJuly 28, 2021

Part 2: Integrate your Shopify eCommerce Store with mParticle

In this blog post, I’ll be embed the mParticle Web SDK within Shopify’s liquid themes and checkout page. This will allow us to capture, analyze and orchestrate events from the Web as well as the back-end of our Shopify store.

Watch a full walkthrough of this integration here!

In my last post on this subject, I showed you how to integrate your Shopify store with mParticle using mParticle’s pre-built connector. This Shopify pre-built connector allows mParticle to configure your Shopify store as a source of truth wherein it will be treated as a server-to-server feed. 

The feed only captures server-side events, however, so this post will cover an extended use case wherein I’ll embed the mParticle Web SDK within Shopify’s liquid themes and checkout page. This will allow you to capture, analyze and orchestrate end-to-end events from the Web and the back-end, resulting in an end-to-end, cross-channel view of your customers.

Configure your Shopify Store to capture events outside the pre-built connector (Screen View, eCommerce Events)

To capture events that aren’t covered by the pre-built connector (e.g., Screen Views, Product Views, Add To Cart, etc.), I’ll be showing you how you can integrate the mParticle Web SDK into your Shopify store. To get started, navigate back to your Shopify Admin Dashboard:

Shopify dashboard

In your dashboard, select "Theme" under "Online Store" on the left menu, then click the "Customize" button on the right-hand side. This should redirect you to the following page:

Example Shopify theme

On the top-left corner, click the ‘…’ icon then select "Edit code." You should then see the following page:

Edit template files in Shopify

Search for `theme.liquid`, and within that file, inject the additional JavaScript below. This will allow you to have the mParticle Web SDK be accessible within every web page of your Shopify store.

<script>
   window.mParticle = {
        config: {
          isDevelopmentMode: true, //switch to false (or remove) for production
             logLevel: "verbose"
        }
      };
      (function(t) {
        window.mParticle = window.mParticle || {};
        window.mParticle.EventType = {
          Unknown: 0,
          Navigation: 1,
          Location: 2,
          Search: 3,
          Transaction: 4,
          UserContent: 5,
          UserPreference: 6,
          Social: 7,
          Other: 8
        };
        window.mParticle.eCommerce = { Cart: {} };
        window.mParticle.Identity = {};
        window.mParticle.config = window.mParticle.config || {};
        window.mParticle.config.rq = [];
        window.mParticle.config.snippetVersion = 2.2;
        window.mParticle.ready = function(t) {
          window.mParticle.config.rq.push(t);
        };
        var e = [
          "endSession",
          "logError",
          "logBaseEvent",
          "logEvent",
          "logForm",
          "logLink",
          "logPageView",
          "setSessionAttribute",
          "setAppName",
          "setAppVersion",
          "setOptOut",
          "setPosition",
          "startNewSession",
          "startTrackingLocation",
          "stopTrackingLocation"
        ];
        var o = ["setCurrencyCode", "logCheckout"];
        var i = ["identify", "login", "logout", "modify"];
        e.forEach(function(t) {
          window.mParticle[t] = n(t);
        });
        o.forEach(function(t) {
          window.mParticle.eCommerce[t] = n(t, "eCommerce");
        });
        i.forEach(function(t) {
          window.mParticle.Identity[t] = n(t, "Identity");
        });
        function n(e, o) {
          return function() {
            if (o) {
              e = o + "." + e;
            }
            var t = Array.prototype.slice.call(arguments);
            t.unshift(e);
            window.mParticle.config.rq.push(t);
          };
        }
        var mp = document.createElement("script");
        mp.type = "text/javascript";
        mp.async = true;
        mp.src =
          ("https:" == document.location.protocol
            ? "https://jssdkcdns"
            : "http://jssdkcdn") +
          ".mparticle.com/js/v2/" +
          t +
          "/mparticle.js";
        var c = document.getElementsByTagName("script")[0];
        c.parentNode.insertBefore(mp, c);
      })("<insert the api key we’ve generated earlier");
  
  
</script>

Click "Save." In the next step, we'll capture the product views and screen views. To do this, search for `product-template.liquid` file, and use the code editor to inject the following JavaScript at the top of the file:

<script >
    function productView() {
        var item = "{{product.title}}";
        var qty;
        if (document.getElementById("Quantity") != null)
            qty = document.getElementById("Quantity").value;

        var size;
        var color;
        if (document.getElementById("SingleOptionSelector-0") != null) {
            size = document.getElementById("SingleOptionSelector-0").value;

            color = document.getElementById("SingleOptionSelector-1").value;
        }
        var SKU;
        if (size != null && color != null)
            SKU = item + "_" + color + "_" + size;
        else
            SKU = item;
        var price = (Number({
            {
                product.price
            }
        }) / 100).toFixed(2);
        var tax = price * .12;
        var product1 = window.mParticle.eCommerce.createProduct(
            item, // Name
            SKU, // SKU
            price, // Price
            qty // Quantity
        );


        var customAttributes = {
            sale: true
        }; // if not passing any custom attributes, pass null
        var customFlags = {
            'Google.Category': 'retail'
        } // if not passing any custom flags, pass null
        mParticle.eCommerce.logProductAction(
            mParticle.ProductActionType.ViewDetail,
            [product1],
            customAttributes,
            customFlags);
    }
document.addEventListener("DOMContentLoaded", function(event) {
    window.mParticle.ready(function() {
        console.log("mParticle WEBSDK has loaded!");
        var page = "{{ product.title }}";
        var pageURL = "{{ shop.url }}{{ product.url }}";
        var pageTitle = "{{ product.title }}" + " Viewed";
        var productTitle = "{{ product.title }}";
        window.mParticle.logPageView("Product Detail Page", {
            page: pageURL,
            "product_title": productTitle
        });

        productView();

        var user = mParticle.Identity.getCurrentUser();
        console.log("getUser");
        if (user == null) console.log("user obj is null");
        else console.log("user obj is not null");
        // alert("Cart Page");

    });
}); 
</script>

Within the same `product-template.liquid page`, we’ll inject additional JavaScript code below, allowing you to capture add-to-card events.

<script>
function addItem() {
    var item = "{{product.title}}";
    var qty = document.getElementById("Quantity").value;
    var size;
    var color;
    if (document.getElementById("SingleOptionSelector-0") != null) {
        size = document.getElementById("SingleOptionSelector-0").value;

        color = document.getElementById("SingleOptionSelector-1").value;
    }
    var SKU = item + "_" + color + "_" + size;
    var price = (Number({
        {
            product.price
        }
    }) / 100).toFixed(2);
    var tax = price * .12;

    var product1 = window.mParticle.eCommerce.createProduct(
        item, // Name
        SKU, // SKU
        price, // Price
        qty // Quantity
    );

    // 2. Summarize the transaction
    var transactionAttributes = {
        Id: 'foo-transaction-id',
        Tax: tax
    };

    var customAttributes = {
        sale: true
    }; // if not passing any custom attributes, pass null
    var customFlags = {
        'Google.Category': 'retail'
    } // if not passing any custom flags, pass null
    mParticle.eCommerce.logProductAction(
        mParticle.ProductActionType.AddToCart,
        [product1],
        customAttributes,
        customFlags,
        transactionAttributes);

}

function checkOut() {
    var item = "{{product.title}}";
    var qty = document.getElementById("Quantity").value;
    var size = document.getElementById("SingleOptionSelector-0").value;
    var color = document.getElementById("SingleOptionSelector-1").value;
    var SKU;
    if (size != null && color != null)
        SKU = item + "_" + color + "_" + size;
    else
        SKU = item;
    var price = (Number({
        {
            product.price
        }
    }) / 100).toFixed(2);
    var tax = price * .12;

    var product1 = window.mParticle.eCommerce.createProduct(
        item, // Name
        SKU, // SKU
        price, // Price
        qty // Quantity
    );

    // 2. Summarize the transaction
    var transactionAttributes = {
        Id: 'foo-transaction-id',
        Tax: tax
    };

    var customAttributes = {
        sale: true
    }; // if not passing any custom attributes, pass null
    var customFlags = {
        'Google.Category': 'retail'
    } // if not passing any custom flags, pass null
    mParticle.eCommerce.logProductAction(
        mParticle.ProductActionType.Checkout,
        [product1],
        customAttributes,
        customFlags,
        transactionAttributes);
}
</script>

Look for the following javascript snippet within the same product-template.liquid page and modify the said button by adding the following onclick attribute: `onclick="addItem(); return true;"`. This will allow you to call the JavaScript function defined above, triggering or generating the add-to-cart event within mParticle. Once you have done this, click "Save."

<div class="product-form__item product-form__item--submit">
       <button type="submit" name="add" onclick="addItem(); return true;" id="AddToCart-{{ section.id }}" class="btn btn--full product-form__cart-submit{% unless current_variant.available %} btn--sold-out{% endunless %}{% if section.settings.enable_payment_button and product.selling_plan_groups == empty %} btn--secondary-accent{% endif %}" {% unless current_variant.available %}disabled="disabled" {% endunless %}>
           <span id="AddToCartText-{{ section.id }}">
               {% unless current_variant.available %}
               {{ 'products.product.sold_out' | t }}
               {% else %}
               {{ 'products.product.add_to_cart' | t }}
               {% endunless %}
           </span>
       </button>
       {% if section.settings.enable_payment_button %}
       {{ form | payment_button }}
       {% endif %}
   </div>

Configure your Shopify Store to stitch the anonymous user from the Web against the known user-generated from the feed

This step is entirely optional as this will cover how you can resolve anonymous users who went to your website initially as a guest user and then eventually either created a Shopify account or did a checkout.

In this section, I’ve already had my mParticle instance configured with the proper Identity Strategy settings using the Profile Conversion strategy. `Email` and `Customer Id` are configured as the identifier attributes as well.

Identity scopes within Shopify

This extra step below will allow you to ensure that any anonymous users from the Web will be reconciled to the known user’s profile created via the webhook that Shopify sends to mParticle through the pre-built connector. Another additional and optional step here is to leverage mParticle’s alias functionality if you want to migrate all events/behaviour captured by mParticle’s Web SDK from the anonymous user to the known user’s profile.

To do this, navigate back to your Shopify Admin dashboard.

Shopify admin settings

Search for "Checkout" in the search bar, then click "Checkout settings." You should then see the following page:

Modify checkout settings in your Shopify dashboard.

Scroll down and look for the Order processing section. Within the "Additional scripts" section, add the following:

<script src="https://jssdkcdns.mparticle.com/js/v2/mparticle.js" type="text/javascript"></script>
<script>
    window.mParticle = {
        config: {
            isDevelopmentMode: true, //switch to false (or remove) for production
            logLevel: "verbose"
        }
    };
    (function(t) {
        window.mParticle = window.mParticle || {};
        window.mParticle.EventType = {
            Unknown: 0,
            Navigation: 1,
            Location: 2,
            Search: 3,
            Transaction: 4,
            UserContent: 5,
            UserPreference: 6,
            Social: 7,
            Other: 8
        };
        window.mParticle.eCommerce = {
            Cart: {}
        };
        window.mParticle.Identity = {};
        window.mParticle.config = window.mParticle.config || {};
        window.mParticle.config.rq = [];
        window.mParticle.config.snippetVersion = 2.2;
        window.mParticle.ready = function(t) {
            window.mParticle.config.rq.push(t);
        };
        var e = [
            "endSession",
            "logError",
            "logBaseEvent",
            "logEvent",
            "logForm",
            "logLink",
            "logPageView",
            "setSessionAttribute",
            "setAppName",
            "setAppVersion",
            "setOptOut",
            "setPosition",
            "startNewSession",
            "startTrackingLocation",
            "stopTrackingLocation"
        ];
        var o = ["setCurrencyCode", "logCheckout"];
        var i = ["identify", "login", "logout", "modify"];
        e.forEach(function(t) {
            window.mParticle[t] = n(t);
        });
        o.forEach(function(t) {
            window.mParticle.eCommerce[t] = n(t, "eCommerce");
        });
        i.forEach(function(t) {
            window.mParticle.Identity[t] = n(t, "Identity");
        });

        function n(e, o) {
            return function() {
                if (o) {
                    e = o + "." + e;
                }
                var t = Array.prototype.slice.call(arguments);
                t.unshift(e);
                window.mParticle.config.rq.push(t);
            };
        }
        var mp = document.createElement("script");
        mp.type = "text/javascript";
        mp.async = true;
        mp.src =
            ("https:" == document.location.protocol ?
                "https://jssdkcdns" :
                "http://jssdkcdn") +
            ".mparticle.com/js/v2/" +
            t +
            "/mparticle.js";
        var c = document.getElementsByTagName("script")[0];
        c.parentNode.insertBefore(mp, c);
    })("insert the api key which we generated earlier");

    window.mParticle.ready(function() {

        var checkoutEmail = "{{checkout.email}}";

        var identityRequest = {
            userIdentities: {
                email: checkoutEmail
            }
        };



        const now = Date.now();
        var previousMPID = window.mParticle.Identity.getCurrentUser().getMPID();

        var previousTime = mParticle.Identity.getCurrentUser().getFirstSeenTime();

        var identityCallback = function(result) {
            var user = result.getUser();

            var destinationmpid = result.body.mpid;

            var aliasCallback = function(result) {
                console.log(JSON.stringify(result));
            };
            mParticle.Identity.aliasUsers({
                destinationMpid: destinationmpid,
                sourceMpid: previousMPID,
                startTime: previousTime,
                endTime: now
            }, aliasCallback);
        }
        window.mParticle.Identity.login(identityRequest, identityCallback);

    });
</script>

Click "Save" and... Congratulations! You have fully completed configuring mParticle capture and collecting additional web events generated from your Shopify Store.

Latest from mParticle

See all insights
Q4 product updates

Company

mParticle Q4 Product Innovations

What is a conversions API

Growth

What Is a Conversions API, and Why Marketers Need It Now

Buying a CDP Today

Growth

Part Eight: Buying a CDP Today