Skip to main content
Skip table of contents

Configure Error Monitoring for Shopify

Features

Guide to configuring the analysis of impactful errors and filtering out the insignificant ones to Shopify Users or Business Processes. Ignore the noise and focus on the issues that are critical to your business! Germain has the ability to help you understand the impact, at scale, of any errors on the end-user or business operations while operating with Shopify. It helps separate critical errors from benign ones and also identifies the new ones.

image-20240227-184050.png

Error on Shopify detected and analyzed by Germain UX

Enable User Error Monitoring for Shopify

Here is how to configure Germain UX’s monitoring to best detect and analyze errors that affect Shopify users.

  • Configure UX Monitoring Profile
    Germain Workspace > Left Menu > Analytics > UX Monitoring Profiles > Shopify

    image-20240227-184408.png

    UX Monitoring Profile for Shopify - Germain UX


  • Sample Code:

    CODE
    germainApm.native.XmlHttpRequest = XMLHttpRequest; // Work-around for sentry.io bocking our requests
    
    function getUsername(window) {
        return new germainApm.native.Promise(function (resolve, reject) {
            germainApm.utils.waitForProperty(window, 'ShopifyAnalytics', function () {
                if (window.ShopifyAnalytics) {
                    if (window.ShopifyAnalytics.meta && window.ShopifyAnalytics.meta.page && window.ShopifyAnalytics.meta.page.customerId) {
                        resolve(String(window.ShopifyAnalytics.meta.page.customerId));
                    }
                    else if (window.ShopifyAnalytics.lib && window.ShopifyAnalytics.lib.trekkie && window.ShopifyAnalytics.lib.trekkie.defaultAttributes.uniqToken) {
                        resolve(window.ShopifyAnalytics.lib.trekkie.defaultAttributes.uniqToken);
                    }
                }
                resolve(null);
            }, function () { return reject(null); }, 20, 500);
        });
    }
    function getSessionId(window) {
        return new germainApm.native.Promise(function (resolve, reject) {
            germainApm.utils.waitForProperty(window, 'ShopifyAnalytics', function () {
                if (window.localStorage && window.localStorage.session_id) {
                    resolve(window.localStorage.session_id);
                }
                else if (window.ShopifyAnalytics && window.ShopifyAnalytics.lib && window.ShopifyAnalytics.lib.trekkie && window.ShopifyAnalytics.lib.trekkie.defaultAttributes.visitToken)
                    resolve(null);
            }, function () { return reject(null); }, 20, 500);
        });
    }
    function clickFactProcessor(fact, event, fireEvent, settings) {
        var target = event.target;
        if (target instanceof HTMLElement) {
            var name_1 = null;
            switch (target.nodeName) {
                case 'BUTTON': {
                    if (target.id === 'continue_button') {
                        name_1 = 'Cart Continue';
                    }
                    else if (target.className) {
                        var classNameTrimmed = target.className.trim();
                        if (classNameTrimmed === 'js-add-to-cart') {
                            name_1 = 'Add To Cart';
                        }
                        else if (classNameTrimmed === 'search-header__submit') {
                            name_1 = 'Search';
                        }
                    }
                    break;
                }
                case 'INPUT': {
                    var inputEvent = target;
                    if (inputEvent.id === 'checkout_button') {
                        name_1 = 'Checkout Now';
                    }
                    else if (inputEvent.name === 'subscribe' && inputEvent.type === 'submit') {
                        name_1 = 'Newsletter Subscription';
                    }
                    else if (inputEvent.name === 'q' && inputEvent.type === 'search') {
                        name_1 = 'Newsletter Subscription';
                    }
                    else if (inputEvent.name === 'updates[]') {
                        name_1 = 'Product Qty Changed';
                    }
                    else if (inputEvent.className) {
                        var classNameTrimmed = inputEvent.className.trim();
                        if (classNameTrimmed === 'cart-add') {
                            name_1 = 'Add To Cart';
                        }
                    }
                    break;
                }
                case 'A': {
                    var anchorTarget = target;
                    if (anchorTarget.href && ~anchorTarget.href.indexOf('/cart/change?line=1&quantity=0')) {
                        name_1 = 'Remove From Cart';
                    }
                    else if (anchorTarget.className) {
                        var classNameTrimmed = anchorTarget.className.trim();
                        if (classNameTrimmed === 'cart-table__content__remove') {
                            name_1 = 'Remove From Cart';
                        }
                    }
                    break;
                }
            }
            if (name_1) {
                fact.name = name_1;
                germainApm.api.createEvent(name_1, {
                    success: true,
                    sequence: fact.sequence + '.' + 0
                });
            }
        }
    }
    function extractHierarchyDimensionFromAPI() {
        var shopifyWindow = window;
        if (shopifyWindow.ShopifyAnalytics && shopifyWindow.ShopifyAnalytics.meta && shopifyWindow.ShopifyAnalytics.meta.page && shopifyWindow.ShopifyAnalytics.meta.page.pageType) {
            return {
                level1: shopifyWindow.ShopifyAnalytics.meta.page.pageType,
                level2: shopifyWindow.ShopifyAnalytics.meta.product && shopifyWindow.ShopifyAnalytics.meta.product.type ? shopifyWindow.ShopifyAnalytics.meta.product.type : undefined // product type
            };
        }
        return undefined;
    }
    function extractBusinessProcessFromAPI() {
        var shopifyWindow = window;
        if (shopifyWindow.ShopifyAnalytics && shopifyWindow.ShopifyAnalytics.meta && shopifyWindow.ShopifyAnalytics.meta.page) {
            if (shopifyWindow.ShopifyAnalytics.meta.page.resourceId) {
                return String(shopifyWindow.ShopifyAnalytics.meta.page.resourceId);
            }
            else if (shopifyWindow.ShopifyAnalytics.meta.page.pageType === 'searchresults' && window.location.search) {
                var match = window.location.search.match(/q=(.*)&/);
                if (match && match.length >= 2) {
                    return match[1];
                }
            }
        }
        return undefined;
    }
    function factProcessor(fact) {
        fact.hierarchy = extractHierarchyDimensionFromAPI();
        fact.businessObject = extractBusinessProcessFromAPI();
    }
    var settings = germainApm.getDefaultSettings();
    settings.constants.logLevelToEmitAsFacts = 'WARN';
    settings.application.metadataProviders['user.name'] = getUsername;
    settings.application.metadataProviders['sessionId'] = getSessionId;
    settings.application.factProcessor = factProcessor;
    settings.plugins.click.factProcessor = clickFactProcessor;
    settings.plugins.pageLoad.factProcessor = function (userClick, events) {
        for (var i = 0; i < events.length; i++) {
            if (events[i].event.type === 'document ready') {
                var page = events[i].page;
                if (page && page.title)
                    userClick.name = 'Navigation ' + page.title;
            }
        }
    };
    germainApm.eventGenerators.customAlert = {
        emits: ['DOM popup opening', 'DOM popup closed'],
        installer: function () { return function () { }; },
    };
    germainApm.start(settings);
    

Automate Identification of “new” errors

To be able to ignore the million of errors that occur every day and know when a new error occur, configure Germain UX’s Categorizationfeature.

Enable Alert and/or Report

Be alerted immediately when a new error occurs. Receive automatic report to help understand error volume trends.

Visualize & Analyze Shopify Errors

Add a portlet and set it up as following:

  • KPI = “JavaScript Popup Dialog” or “Javascript Console Event” KPI
    (or any other KPI you have created in connection with the above error monitoring).

  • Pivot = “Message”

  • Filters = “userError == true”


image-20240227-184754.png

Add “JavaScript Popup Dialog” KPI for Shopify Error analysis - Germain UX

This is how the portlet would look like:

image-20240227-184703.png

Shopify Error portlet - Germain UX

  • Exclude Errors
    And once your portlet is created, you can always exclude/include additional errors, as following:

    image-20240227-165033.png

    Filter in or out specific Salesforce errors - Germain UX

Component: Engine, RUM JS

Feature Availability: 2022.1 or later

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.