Menu
Menu Sheet Overlay
Search
Search Sheet

Built-In Events

    Table of contents

    Pageview events #

    Receiving pageview events #

    Most of the analytics services that Mobify supports already implement a pageview event. However, if you need to alter how the event is set up, add a pageviewEvent function override to your analytics connector.

        import GoogleTagManager from 'progressive-web-sdk/dist/analytics/connectors/google-tag-manager/connector'
    
        export default class MyGTM extends GoogleTagManager {
            constructor() {
                super('My GTM', 'GTM-#######')
            }
    
    +        pageviewEvent(payload, state) {
    +            // Shape given arguments to the expected format that
    +            // the analytic platform requires
    +        }
        }
    

    The payload should have the following structure:

    payload = {
        templatename
    }
    

    Dispatching pageview events from the PWA #

    The pageview event should be already instrumented in the PWA when you generate a new project with Mobify’s project generator. If you do not see a pageview events firing, check inside web/app/template.jsx where it should be instrumented like this:

    import {onPageReady, trackPerformance} from 'progressive-web-sdk/dist/analytics/actions'
    ...
    const initPage = (component) => (url, routeName) => (dispatch, getState) => {
        ...
        dispatch(onPageReady(routeName))
        ...
    }
    

    Verifying that pageview events are working #

    1. Turn on debugging mode
    2. Open the web developer console and view some pages in the PWA
    3. You should see the following in the console log:

      • Project ID: This should match the Mobify project slug for the project
      • Url / Location: This should match the URL displayed in the address bar
      • Path / Page: This should just be the URL path without the domain
      • Page Title: This should match the title of the page even across soft navigations
      • Template Name: This should match the template of the page
      • Status: This will be undefined until the PWA has some navigations offline and comes back online. When the PWA comes back online, it will send multiple pageviews with these possible values:
        • offline_success - When user viewed a saved page while offline
        • offline_failed - When user tried to view an uncached page while offline

    Set currency events #

    Receiving set currency events #

    Add a setCurrencyEvent function override to your analytics connector.

        import GoogleTagManager from 'progressive-web-sdk/dist/analytics/connectors/google-tag-manager/connector'
    
        export default class MyGTM extends GoogleTagManager {
            constructor() {
                super('My GTM', 'GTM-#######')
            }
    
    +        setCurrencyEvent(payload, state) {
    +            // Shape given arugments to the expected format that
    +            // the analytic platform requires
    +        }
        }
    

    The payload should have the following structure:

    payload = {
        currencyCode
    }
    

    Dispatching set currency events from the PWA #

    There are 2 instances when you should dispatch a set currency code event:

    If the user is able to change the currency within the UI, you should also add a UI Interaction event. To do this, provide the data-analytics-name and data-analytics-content props on the element used to set the currency.

    import {UI_NAME} from 'progressive-web-sdk/dist/analytics/data-objects/'
    
    <Link
        onClick={() => { updateCurrency(currency) }}
        data-analytics-name={UI_NAME.setCurrency}
        data-analytics-content={currency}
    >
        {text}
    </Link>
    

    Verifying that set currency events are working #

    There are no console message displayed for this change. However, you should be able to see the additional currency code setting in the Google Analytics tracker:

    Purchase events #

    Receiving purchase events #

    Add a purchaseEvent function override to your analytics connector.

        import GoogleTagManager from 'progressive-web-sdk/dist/analytics/connectors/google-tag-manager/connector'
    
        export default class MyGTM extends GoogleTagManager {
            constructor() {
                super('My GTM', 'GTM-#######')
            }
    
    +        purchaseEvent(payload, state) {
    +            // Shape given arguments to the expected format that
    +            // the analytic platform requires
    +        }
        }
    

    The payload should have the following structure:

    payload = {
        transaction: {
            id,
    
            // Following keys are optional
            revenue             // Grand total (including shipping and tax)
            affiliation
            tax
            shipping
            list
            step
            option
        },
        products: [             // Product details in cart will be pulled from redux store
            {
                id
                name
    
                // Following keys are optional
                price
                quantity
                stock
                category
                brand
                variant
                list
                position
                coupon
                size
                color
            },
            ...
        ]
    }
    

    Dispatching purchase events from the PWA #

    In order to take advantage of the automatic instrumentation of purchase events, you need to import the result action receiveCheckoutConfirmationData from the Integration Manager and dispatch it to send the order details.

    In the example below, the confirmation page will call initCheckoutConfirmationPage to initialize the page. In this function, we dispatch receiveCheckoutConfirmationData to store confirmation data in the Redux store and send the purchase event.

    import receiveCheckoutConfirmationData from 'mobify-integration-manager/dist/integration-manager/api/checkout/results'
    
    
    export const initCheckoutConfirmationPage = (url) => (dispatch) => {
        return dispatch(fetchConfirmationData())
            .then((confirmationData) => {
                // The confirmation Data contains `orderNumber`
                // Revenue, tax and products will be taken from the redux store automatically
                dispatch(receiveCheckoutConfirmationData(confirmationData))
            })
    }
    

    Verifying that purchase events are working #

    1. Turn on debugging mode
    2. Open web developer console and complete a purchase in the project
    3. You should see the following in the console log:

      Make sure the following conditions are true:

      • There is only 1 purchase event to the Engagement Engine
      • There is only 1 purchase event to the Mobify Google Analytics
      • The transaction id matches the backend data
      • There are the same number of purchase.product events as there are products in the order
      • The revenue matches the grand total of the order (including tax, fee, shipping)
      • Each product details matches the backend data
      • Currency Code is included if available

    Performance events #

    Performance metric terminology #

    Receiving performance events #

    Add a performanceEvent function override to your analytics connector.

        import GoogleTagManager from 'progressive-web-sdk/dist/analytics/connectors/google-tag-manager/connector'
    
        export default class MyGTM extends GoogleTagManager {
            constructor() {
                super('My GTM', 'GTM-#######')
            }
    
    +        performanceEvent(payload, state) {
    +            // Shape given arguments to the expected format that
    +            // the analytic platform requires
    +        }
        }
    

    The payload should have the following structure:

    // PWA First Load (Hard navigation)
    payload = {
        bundle
        pageStart                   // Page Start (Available for supported browser)
        mobifyStart                 // Mobify Start
        timingStart                 // This will be pageStart if available. Otherwise, mobifyStart
        firstPaint                  // First Paint (Available for supported browser)
        firstContentfulPaint        // First Contentful Paint (Available for supported browser)
        appStart                    // App Start
        templateWillMount           // Page Paint
        templateDidMount            // Page Contentful Paint
        templateAPIEnd              // Page Content Load
        fullPageLoad                // Full Page Load
        timeToInteractive           // Time to Interactive (Available for supported browser)
        isSavedPage                 // Is Saved Page
    }
    
    // PWA Sub-sequent Load (Soft navigation)
    payload = {
        bundle
        timingStart
        templateDidMount
        templateAPIEnd
        fullPageLoad
        isSavedPage
    }
    

    Dispatching performance events from the PWA #

    Performance events should be already instrumented in PWA when you generate a new project with Mobify’s project generator. If you do not see performance events firing, there are several files you should check where it should be instrumented like this:

    In web/app/router.jsx

    import {PERFORMANCE_METRICS} from 'progressive-web-sdk/dist/analytics/data-objects/'
    import {trackPerformance} from 'progressive-web-sdk/dist/analytics/actions'
    
    let OnChange = () => {
        trackPerformance(PERFORMANCE_METRICS.templateWillMount)
    }
    
    if (isRunningInAstro) {
        OnChange = (prevState, nextState, replace, callback) => {
            ...
            pwaNavigate({url: getURL(nextState)}).then(() => {
                trackPerformance(PERFORMANCE_METRICS.templateWillMount)
                ...
            })
        }
    }
    
    class Router extends React.Component {
        componentWillMount() {
            trackPerformance(PERFORMANCE_METRICS.templateWillMount)
        }
    

    In web/app/template.jsx

    import {onPageReady, trackPerformance} from 'progressive-web-sdk/dist/analytics/actions'
    ...
    
    const initPage = (component) => (url, routeName) => (dispatch, getState) => {
        ...
        return fetchResolve
            .then(() => {
                trackPerformance(PERFORMANCE_METRICS.isSavedPage, hasFetchedCurrentPath(currentState) ? 'true' : 'false')
                dispatch(setFetchedPage(url))
            })
            .then(() => {
                dispatch(onPageReady(routeName))
                trackPerformance(PERFORMANCE_METRICS.templateAPIEnd)
            })
            ...
    }
    
    const template = (WrappedComponent) => {
        class Template extends React.Component {
            ...
            componentDidMount() {
                trackPerformance(PERFORMANCE_METRICS.templateDidMount)
                ...
            }
            ...
            componentDidUpdate() {
                trackPerformance(PERFORMANCE_METRICS.templateDidMount)
                ...
            }
    

    For each page container, make sure template() is used

    export default template(Home)
    

    Verifying that performance events are working #

    1. Turn on debugging mode
    2. Open web developer console and navigate in the PWA
    3. You should see the following in the console log:

      A hard navigated performance event will have delay of about 5 seconds.

      Below is an example of a soft navigated performance event:

    Add to cart / Remove from cart events #

    Receiving cart events #

    Add an addToCartEvent function override and a removeFromCartEvent function override to your analytics connector.

        import GoogleTagManager from 'progressive-web-sdk/dist/analytics/connectors/google-tag-manager/connector'
    
        export default class MyGTM extends GoogleTagManager {
            constructor() {
                super('My GTM', 'GTM-#######')
            }
    
    +        addToCartEvent(payload, state) {
    +            // Shape given arugments to the expected format that
    +            // the analytic platform requires
    +        }
    
    +        removeFromCartEvent(payload, state) {
    +            // Shape given arugments to the expected format that
    +            // the analytic platform requires
    +        }
        }
    

    The payload should have the following structure:

    payload = {
        cart: {
            type
            count
            subtotal
        },
        product: {
            id
            name
    
            // Following keys are optional
            price
            quantity
            stock
            category
            brand
            variant
            list
            position
            coupon
            size
            color
        }
    }
    

    Dispatching cart events from the PWA #

    Cart events should be already instrumented in PWA when you generate a new project with Mobify’s project generator. If you do not see cart events firing or you are using overridden Integration Manager commands, make sure that the cart events are instrumented. Mobify uses these analytics events for automated cart abandonment push messages for customers.

    Add to cart #

    Instrument this event whenever there is an add to cart action, including when the user does any of the following:

    In your command, make sure you dispatch the addToCart command.

    import IntegrationManager from 'mobify-integration-manager/dist/'
        ...
        // Add an item to cart
        dispatch(IntegrationManager.cart.addToCart(productId, qty, variant))
        ...
        // Update an item in cart
        dispatch(IntegrationManager.cart.updateCartItem(itemId, quantity, productId, variant))
        ...
        // Update the quantity of an item in cart
        dispatch(IntegrationManager.cart.updateItemQuantity(itemId, newQuantity))
    

    If you are unable to dispatch the command, you will need to invoke an analytics action to dispatch the cart analytics.

    import {EVENT_ACTION} from 'progressive-web-sdk/dist/analytics/data-objects/'
    import {dispatchCartAnalytics} from 'progressive-web-sdk/dist/analytics/actions'
    ...
        dispatchCartAnalytics(EVENT_ACTION.addToCart, dispatch, getState, productId, quantityAdded)
    

    The above command will construct the remaining required product information from the Redux store using selectors.

    Remove from cart #

    Instrument this event whenever there is an remove from cart action, including when the user does any of the following:

    In your command, make sure you dispatch the removeFromCart command.

    import IntegrationManager from 'mobify-integration-manager/dist/'
        ...
        // Remove an item from cart
        dispatch(IntegrationManager.cart.removeFromCart(productId))
        ...
        // Update an item in cart
        dispatch(IntegrationManager.cart.updateCartItem(itemId, quantity, productId, variant))
        ...
        // Update the quantity of an item in cart
        dispatch(IntegrationManager.cart.updateItemQuantity(itemId, newQuantity))
    

    If you are unable to dispatch the command, you will need to invoke an analytics action to dispatch the cart analytics.

    import {EVENT_ACTION} from 'progressive-web-sdk/dist/analytics/data-objects/'
    import {dispatchCartAnalytics} from 'progressive-web-sdk/dist/analytics/actions'
    ...
        dispatchCartAnalytics(EVENT_ACTION.removeFromCart, dispatch, getState, productId, quantityRemoved)
    

    The above command will construct the remaining required product information from the Redux store using selectors.

    Verifying that cart events are working #

    1. Turn on debugging mode
    2. Open web developer console and perform the following actions on the PWA:
      • Add an item to cart
      • Remove an item from cart
      • Interact with the quantity stepper with an item in cart
      • Add an item from wishlist
    3. You should see the following in the console log:

      Add to cart

      Remove from cart

      • Cart Count should be the total number of items in the cart
      • Subtotal should be the total amount displayed to the customer

    UI interaction events #

    UI interaction events are analytics events that resulted from an action in the PWA. For example:

    In order to name analytics events more consistently, we’ve adopted a naming scheme inspired by this article: Closing the gap between data and product development.

    All UI interaction events have at least 4 arguments:

    This results in the combination of Subject + Action + Object as our Engagement Engine analytics action. For example:

    (For simplicity’s sake, we decided to ignore pluralization and verb tenses.)

    Receiving UI interaction events #

    Add a uiInteractionEvent function override to your analytics connector.

        import GoogleTagManager from 'progressive-web-sdk/dist/analytics/connectors/google-tag-manager/connector'
    
        export default class MyGTM extends GoogleTagManager {
            constructor() {
                super('My GTM', 'GTM-#######')
            }
    
    +        uiInteractionEvent(payload, state) {
    +            // Shape given arugments to the expected format that
    +            // the analytic platform requires
    +        }
        }
    

    The payload should have the following structure:

    payload = {
        subject
        action
        object
        name
        content
    }
    

    Dispatching UI interaction events from the PWA and validating them #

    We have implemented several SDK components to automatically trigger analytics events:

    Some of these SDK components require some analytics implementation from the developers.

    Buttons #

    Button analytics are built-in with the SDK Button component. Developers just need to supply the context of the button’s purpose.

    import Button from 'progressive-web-sdk/dist/components/button'
    import {UI_NAME} from 'progressive-web-sdk/dist/analytics/data-objects/'
    ...
        <Button
            data-analytics-name={UI_NAME.checkout}
        >
            Checkout
        </Button>
    

    Let’s say there are 2 Checkout buttons on the same page. We can make use of the content to distinguish the two buttons.

    import Button from 'progressive-web-sdk/dist/components/button'
    import {UI_NAME} from 'progressive-web-sdk/dist/analytics/data-objects/'
    ...
        <Button
            data-analytics-name={UI_NAME.checkout}
            data-analytics-content={UI_NAME.top}
        >
            Checkout
        </Button>
    ...
         <Button
            data-analytics-name={UI_NAME.checkout}
            data-analytics-content={UI_NAME.bottom}
        >
            Checkout
        </Button>
    

    You should see the following when you interact with the button in debugging mode:

    Swatches #

    Swatch analytics are built-in with the SwatchItem component in the SDK. Developers need to supply the context of the swatch’s category and the value of the individual swatch item.

    import {Swatch, SwatchItem} from 'progressive-web-sdk/dist/components/swatch'
    ...
        <Swatch ... >
            <SwatchItem
                analyticsName="color"
                analyticsContent={swatchValue}
            >
                ...
            </SwatchItem>
            ...
        </Swatch>
    

    You should see the following when you interact with the swatch item in debugging mode:

    Inputs #

    Input analytics events are automatically tracked when a user focuses on the inputs. This applies to any of the following HTML tags: input, select, and textarea. Developers need to supply the context for each of these tags.

    import {UI_NAME} from 'progressive-web-sdk/dist/analytics/data-objects/'
    ...
    render() {
        return (
            ...
            <input type="text" data-analytics-name={UI_NAME.firstName} />
            <input type="radio" data-analytics-name={UI_NAME.shippingMethod} />
            <input type="checkbox" data-analytics-name={UI_NAME.subscribe} />
            <select data-analytics-name={UI_NAME.country}>
                ...
            </select>
            <textarea data-analytics-name={UI_NAME.message} />
            ...
        )
    }
    

    You should see the following when you interact with the inputs in debugging mode:

    Form errors #

    There are 2 types of form errors that Mobify tracks:

    To instrument these events, verify that the following conditions are true:

    <form id={SIGN_IN_FORM_NAME} data-analytics-name={UI_NAME.login}>
        ...
    </form>
    ...
    const ReduxSignInForm = reduxForm({
        form: SIGN_IN_FORM_NAME
    })(SignInForm)
    

    You should see the following when you interact with the inputs in debugging mode:

    Change language event #

    If your project supports multiple languages, track when the user changes their language preferences. This should be done through a UI interaction event.

    To send the UI interaction event, add the data-analytics-name and data-analytics-content props to the element the user interacts with to select a language. The data-analytics-name prop should be set to "set_language" and the data-analytics-content props should be set to the identifier for the selected language.

    import {UI_NAME} from 'progressive-web-sdk/dist/analytics/data-objects/'
    
    <Link
        onClick={() => { changeLocale(language) }}
        data-analytics-name={UI_NAME.setLanguage}
        data-analytics-content={language}
    >
        {text}
    </Link>
    

    Using UI interaction events in a custom connector #

    It is possible to track UI interaction events in a custom connector. In your connector, add the function uiInteractionEvent.

    import {UIInteraction} from 'progressive-web-sdk/dist/analytics/data-object'
    
    // ...
    
    uiInteractionEvent(payload) {
        // Convert the payload into a UIInteraction data object to ensure that it is properly structured
        const uiInteraction = new UIInteraction(payload, [], {}, false)
    
        // uiInteraction contains the following attributes
        // subject (required, ex. User)
        // action (required, ex. Open)
        // object (required, ex. Modal)
        // name (optional)
        // content (optional)
    
        // Handle the UI interaction event
    }
    

    Dispatching UI interaction events from outside the PWA #

    You can also send UI interaction events from outside the PWA like this:

    window.Progressive.analytics.send({
        subject: window.Progressive.analytics.constants.UI_SUBJECT.app,
        action: window.Progressive.analytics.constants.UI_ACTION.display,
        object: window.Progressive.analytics.constants.UI_OBJECT.button,
        name: window.Progressive.analytics.constants.UI_NAME.applePay
    })
    

    We also made these constants available within the scope of the window object.

    window.Progressive.analytics.constants = {
        UI_SUBJECT,
        UI_ACTION,
        UI_OBJECT,
        UI_NAME
    }