Menu
Menu Sheet Overlay
Search
Search Sheet

      Built-In Events

      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:

      • Initial PWA setup in web/app/containers/app/container.jsx

          import {setCurrencyCode} from 'progressive-web-sdk/dist/analytics/actions'
        
          class App extends React.Component {
              ...
              componentWillMount() {
                  ...
                  this.props.setInitialCurrencyCode('CAD')
              }
          ...
          const mapDispatchToProps = {
              ...
              setInitialCurrencyCode: setCurrencyCode
          }
              ...
      • When the displayed currency on customer’s site has changed

          import {setCurrencyCode} from 'progressive-web-sdk/dist/analytics/actions'
        
              ...
              dispatch(setCurrencyCode(currencyCode))
              ...

      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

      • Page Start: a high resolution timestamp collected from the Web Performance API. This metric indicates the time when the browser starts to navigate.
      • Mobify Start: the time when the Mobify tag starts to load loader.js.
      • First Paint and First Contentful Paint: metrics defined from Chrome PerformancePaintTiming Interface. First paint time is the time that Chrome takes to finish the critical rendering path that typically includes the app skeleton. Images and other assets do not block the first paint. First Contentful Paint is the point when the browser renders the first bit of content from the DOM. This content may be some text or an image.
      • App Start: the time from Mobify Start to when the loader.js starts to initialize the PWA.
      • Page Paint: the time taken by the router of the PWA. Each route change will trigger the Analytics Manager to track the time it takes.
      • Page Contentful Paint: the time when the React component for the pages is mounted. At this stage, the user can see the shape of the page through placeholder objects (skeletons), but the data required to fill in those placeholders has not been fetched yet.
      • Page Content Load: the time when the data is returned from the server and the necessary information such as product names and prices are rendered on the page, but the images are not rendered.
      • Full Page Load: the time when all images have rendered on the page.
      • Time to Interactive (TTI): the time until the page being loaded is considered usable and will respond to user input. This is done with TTI Polyfill
      • Is saved page: The PWA saves the history of the pages in a variable so that it can navigate between saved pages instantly.

      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:

      • Adds an item to cart from a product description page
      • Adds an item to cart from a wishlist
      • Updates an item that results in an increasing quantity

      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:

      • Removes an item from the cart page or mini cart
      • Updates an item that results in a decrease in quantity

      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:

      • A user clicks on a button
      • A user focuses on an input
      • A user opens a modal
      • The app displays an error
      • The app receives an internal error
      • …etc

      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:

      • Subject - Who is acting
      • Action - What action is being performed
      • Object - What is being affected
      • Name - The name of the specific object
      • Content (Optional) - Extra information related to this object

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

      • userClickButton
      • userFocusInput
      • appOpenModal
      • appReceiveError
      • appDisplayError

      (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:

      • AccordionItem
      • Buttons
      • CardInput
      • CardVerification
      • Carousel
      • ExpiryDate
      • Pagination
      • PasswordInput
      • Search
      • Share
      • Stepper
      • Swatch

      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:

      • Sync errors - Errors that resulted from an unexpected input format
      • Submission errors - Errors that resulted from a backend server

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

      • The id is defined on the form tag
      • The data-analytics-name is defined on the form tag
      • The form id is the same id as the Redux form configuration
      <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
      }

      IN THIS ARTICLE:

      Feedback

      Was this page helpful?