menu
Menu
Mobify DevCenter
search_icon_focus

Analytics Integrations

Introduction

Analytics Integrations is a data layer for interacting with client-side analytics services in your PWA. It centralizes code for tracking analytics events and queues events while offline:

import {AnalyticsManager} from 'progressive-web-sdk/dist/analytics-integrations/analytics-manager'
import {GoogleAnalyticsConnector} from 'progressive-web-sdk/dist/analytics-integrations/connectors/google-analytics.js'
import {PAGEVIEW} from 'progressive-web-sdk/dist/analytics-integrations/types'
const analyticsManager = new AnalyticsManager({
connectors: [
new GoogleAnalyticsConnector({
trackerName: 'myTracker',
trackerId: 'UA-123'
})
]
})
analyticsManager.track(PAGEVIEW, {
templateName: 'product-details-page'
})

The AnalyticsManager instance sends events to its connectors. Each connector forwards the event to an analytics service, like Google Analytics or Adobe Analytics. Events are the named JavaScript objects containing analytics data that connectors send to their analytics service.

Connectors

Connectors are classes that implement the AnalyticsConnector interface. They send events to an analytics service, and load any scripts that are needed to use the analytics service. Here is an example of a connector set up to Google Analytics:

import {PAGEVIEW} from 'progressive-web-sdk/dist/analytics-integrations/types'
import {loadScript} from 'progressive-web-sdk/dist/analytics-integrations/utils'
export class GoogleAnalyticsConnector {
// Returns a Promise which resolves when scripts required
// to interact with the analytics service are loaded.
load() {
return loadScript('https://www.google-analytics.com/analytics.js').then(() => {
const ga = (this.ga = window.ga)
ga('create', 'UA-123', {name: 'myTracker'})
return Promise.resolve()
})
}
// Forward events to the analytics service.
track(type, data) {
switch (type) {
case PAGEVIEW:
this.tracker.send('pageview', data)
break
default:
return null
}
return data
}
}

Analytics Integrations provides these pre-built connectors:

Events

Calling AnalyticsManager.track(eventType, eventData) sends an event, like this:

import {PAGEVIEW} from 'progressive-web-sdk/dist/analytics-integrations/types'
import {analyticsManager} from 'pwa/app/analytics/index'
const eventType = PAGEVIEW
const eventData = {
templateName: 'product-details-page'
}
analyticsManager.track(eventType, eventData)

This example includes two constants:

  • eventType is an arbitrary string used to identify a class of events.
  • eventData is an object of meta information that gives context to the event.

Analytics Integrations defines several data types for events.

Declarative syntax for tracking user interface events

Using AnalyticsManager.track(), you can track UI interactions such as button clicks:

import {UIINTERACTION} from 'progressive-web-sdk/dist/analytics-integrations/types'
import {analyticsManager} from 'pwa/app/analytics/index'
const TrackingButton = () => (
<button
onclick={() => {
analyticsManager.track(UIINTERACTION, {
subject: 'user',
action: 'Click',
object: 'Button',
name: 'promo-call-to-action',
content: '50off-promo'
})
}}
/>
)

However, this syntax can get verbose if you’re tracking many events. The declarative syntax reduces repetition by allowing you to use HTML data attributes to track events:

const TrackingButton = () => (
<button data-analytics-name="promo-call-to-action" data-analytics-content="50off-promo" />
)

Adding data-analytics-name and data-analytics-content will automatically track a UIINTERACTION event for any focus, change, and click events that occur on your element or its children element.

  • data-analytics-name: a required attribute that sets the name property of event data. It helps identify which element was used.
  • data-analytics-content: an optional attribute that sets the context property of event data. As the name implies, this attribute helps provide context about the event. The select elements, and the checkbox and radio input elements are automatically set with a boolean value.

In the example above, the data properties subject, action, and object are not included because they’re automatically set with values from the JavaScript Event triggered. You can read more about all the event data properties in the data types reference.

Automatic event validation

Analytics Integrations offers automatic event validation, ensuring that incoming event data matches its corresponding data type schema. The automatic validation occurs when your PWA is run in a non-production environment, or when the debug flag is set to true.

Tracking events while offline

Analytics Integrations also includes offline queuing. When the browser is offline, tracked events are queued. When the browser is able to reconnect to the network, events are flushed from the queue to connectors in the order in which they occurred.

Implementing the AnalyticsManager class

The scaffold already includes a starting implementation of AnalyticsManager:

Using Redux with the AnalyticsManager class

If you’re using Redux in your app, you may want to couple Redux actions with analytics events. However, Redux actions may be used in many places across your app, and calling AnalyticsManager.track() in each place can be tedious and error-prone.

Instead, you can implement a Redux middleware to call AnalyticsManager.track() in one spot for each action.

Given this Redux action:

// app/actions.js
export const PAGE = 'PAGE'
export const onPageview = (templateName) => {
type: PAGE,
payload: {
templateName
}
}

You can create an analytics middleware like this:

// app/analytics/middleware.js
import {getAnalyticsManager} from './index'
import {PAGE} from '../actions'
import {PAGEVIEW} from 'progressive-web-sdk/dist/analytics-integrations/types'
const analyticsManager = getAnalyticsManager() // your analyticsManager instance.
const analyticsMiddleware = (store) => (next) => (action) => {
const {payload, type} = action
switch (type) {
case PAGE:
analyticsManager.track(PAGEVIEW, {
templateName: payload.templateName
})
break
default:
break
}
return next(action)
}
export default analyticsMiddleware

Include your middleware using the Redux method applyMiddleware() when creating your store, like this:

// app/store.js
import {createStore, applyMiddleware} from 'redux'
import analyticsMiddleware from './analytics/middleware'
// Reducer
export const reducer = (state, action) => {
const {type, payload} = action
switch (type) {
case PAGE: {
return {
...state,
cart: payload
}
}
default:
return state
}
}
const store = createStore(reducer, {}, applyMiddleware(analyticsMiddleware))

Debugging the AnalyticsManager class

To debug tracked events, turn on the debug flag to print logs to your browser console.

There are two ways to enable the debug flag:

1. Using the DEBUG environment variable

When you start your dev server, you can set the environment variable DEBUG with this command:

DEBUG=true npm run start

2. Directly in code:

The debug flag is set when creating an instance of AnalyticsManager, so you can modify it directly like this:

import {AnalyticsManager} from 'progressive-web-sdk/dist/analytics-integrations/analytics-manager'
const analyticsManager = new AnalyticsManager({debug: true})

That’s it! After reading this article, you’ve gotten to know all the key concepts you’ll need to integrate analytics services into your Mobify PWA. For further reading, check out our article on Validating Analytics Data During Launch.