analytics-opencare
v0.5.11
Published
This README is structured to allow you to read top down when getting started. This package is meant to support all of Opencare's analytics needs, and is therefore opinionated on what types of events and properties are supported. It's recommended you read
Downloads
121
Readme
Getting Started
This README is structured to allow you to read top down when getting started. This package is meant to support all of Opencare's analytics needs, and is therefore opinionated on what types of events and properties are supported. It's recommended you read through this doc before getting started to give you a good sense of what this package can and cannot do for you.
EXTREMELY IMPORTANT: This package is integrated with Fullstory and Hotjar, which is not HIPAA compliant! To protect user information, all areas of PPI in your application need to be wrapped in .sensitive-data data-hj-suppress
in order to prevent it from being sent to Fullstory and Hotjar. Please ensure you have protected your application before importing and initializing this package.
Table of Contents
- Installation in React
- Installation in AngularJS
- Translating Requests From Data Team
- Tracking Events
- Event Properties
- Additional methods
- Third Party Integrations
- Testing and this package
- Deployment
- Updating Our Custom Schemas
Installation in React
- Add the analytics-opencare package into your package.json under
dependencies
"analytics-opencare": "^0.3.0"
- In your app, in a top level JS file (wherever works for you, app.js is a great default place), initialize the analytics package:
import OpencareAnalytics from 'analytics-opencare';
const OpencareAnalytics = new OpencareAnalytics();
OpencareAnalytics.initialize(app_id);
Parameters
app_id
: String, required. This needs to follow the naming pattern application_name:environemnt. (e.g. 'search-v2:staging', 'search-v2:production')
Installation in AngularJS
- Add the analytics-opencare package into your package.json under
dependencies
"@bower_components/analytics-opencare": ""
- In your
<body />
tag, before yourapp.js
script tag, add the following script tag
<script src="/bower_components/analytics-opencare/dist/index.js"></script>
- In the same file you added the above script tag, right above the app.min.js build step (comment may look like
<!-- build:js /dist/js/app.min.js -->
) Add the following
<script>
// Set global instance of Analytics package
OpencareAnalytics = new OpencareAnalytics();
</script>
Bonus: This will allow you to call OpencareAnalytics
in any component without importing it!
In your
Gruntfile.js
in yourclient.options.predef
array add'OpencareAnalytics'
.In your
app.js
initialize the analytics package:
OpencareAnalytics.initialize(app_id);
Parameters
app_id
: String, required. This needs to follow the naming pattern application_name:environemnt. (e.g. 'search:staging', 'search:production')
Testing this Package Locally
After making your changes you'll probably need to test them in your front-end app, but this package may not be ready to release yet, so you'll need to install the package manually.
First, upgrade the version number of the analytics-opencare
package to prevent headaches. (Note, the version number when releasing should always be previous number + 1, don't forget to change this back if you do multiple iterations of this).
In analytics-opencare
, run yarn tarball
which will clean, compile, and pack into a tarball.
mv
the tarball to the app you want to use it in (root of the app is fine).
In the root dir of the app you're testing the upgrade in, run yarn add file:analytics-opencare-0.x.yz.tgz
You may need to restart your app for the changes to reflect properly.
Done!
This script will automate the process for search-v2, you may just need to change the file paths to match your file structure:
cd ~/opencare/analytics-opencare
nvm use default
yarn tarball
mv analytics-opencare-0.*.tgz ~/opencare/search-v2/analytics-opencare-ball.tgz
cd ~/opencare/search-v2
nvm use
yarn remove analytics-opencare
rm -rf ~/opencare/search-v2/node_modules/analytics-opencare
yarn cache clean
yarn add file:analytics-opencare-ball.tgz
rm analytics-opencare-ball.tgz
Before pushing your app's changes, make sure you yarn remove analytics-opencare
and yarn add analytics-opencare
to be on the live version.
Troubleshooting
Try fully restarting the app and clearing browser cache, hard reloading browser etc.
Try yarn remove analytics-opencare
before installing the tarball.
Try the usual package troubleshooting steps: delete node_modules
and reinstall, run yarn cache clean
etc.
Translating Requests From Data Team
The data team will request events in a format that is closer to what the data will look like on their end, rather than the format this library requires. To learn how to translate these requests, read more here.
Tracking Events
All tracking events accept the same parameters, detailed in Event Properties. Below are the events we support:
| Method | Also known as | Description |
| --------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------ |
| trackPageView() | LOADED
| Is used to track page views (or equivalent action in single page apps). |
| trackClick() | SELECTED
| For when a user clicks on something - say an option in the funnel, possibly a button, or even a navigational link. |
| trackForm() | ENTERED
| For when a user fills out any basic form (not conversions, logins, or signups) and should only be called on submit. |
| trackConversion() | REQUESTED
| For when a user fills out a form that is considered a conversion – say when a user requests an appointment. |
| trackLogIn() | LOGGEDIN
| For when a user fills out a login form – say whenever a user uses their registration information to enter their account. |
| trackSignUp() | REGISTERED
| For when a user fills out a signup form – say any time a new user provides an email/phone number. |
| trackCancel() | CANCELLED
| For when a user cancels something – say any time a patient cancels an appointment. |
| trackVerified() | VERIFIED
| For when a user verifies something such as their email or phone. |
Additionally, all of our tracking events send out a console.log()
in non-production environments to help you QA. These logs will look like: ["OpencareAnalytics ->", EVENT_TYPE, EVENT_NAME, PROPERTIES, THIRD_PARTIES_TRIGGERED]
Event Properties
All tracking events take an object as their parameter, with all of the following being passed within. For example:
OpencareAnalytics.trackClick({
pageType: OpencareAnalytics.pageTypes.FUNNEL,
name: "wizard",
section: "gender",
content: {
gender: "not-important"
}
});
Additionally, all values are sanitized to be lower case and to remove all characters that aren't one of: alphanumerical, space, dash, comma, period, @ sign, or ampersand.
Each parameter is explained below, but here's a high level summary of all supported parameters:
| Parameter | Also known as | Type, required |
| --------------------------------------------- | ------------------ | ---------------- |
| pageType | page_type
| string, required |
| pageName | page_name
| string, required |
| content | feature_value
| object, optional |
| name | feature_name
| string, optional |
| section | feature_section
| string, optional |
| position | feature_position
| array, optional |
| userId | user_id
| number, optional |
| patientId | patient_id
| number, optional |
| providerId | provider_id
| number, optional |
| practiceId | practice_id
| number, optional |
| doctorId | doctor_id
| number, optional |
| userSuppliedLocation | user_location
| object, optional |
| matchId | match_id
| number, optional |
| appointmentId | appointment_id
| number, optional |
| fullStory | n/a | object, optional |
| hotjar | n/a | object, optional |
PageType
Key: pageType. Type: String. Required. This property is allowed to be one of the following list:
- landing
- funnel
- funnel-lead
- practice-onboard-funnel
- confirmation
- confirmation-lead
- form
- form-lead
- mini-form-lead
- form-error
- survey
- practice-profile
- content
- match-results
- waiting
- listing
- login
- appointment-manager
- appointment-list
- account-manager
- referrals
- offer-claim-manager
- instant-book-manager
- performance-view
- provider-availability
- profile-manager
- settings-manager
- invoice-manager
- opencare-hours-manager
- provider-manager
- error
- partner
- partner-lead
- concierge
When data requests an event, they will use one of the strings in the above list. However rather than manually typing these values, they can be easily accesible by OpencareAnalytics.pageTypes.<SNAKE_CASE_PAGE_TYPE>
. The naming format follows the above but in snake case (e.g. LANDING = landing, FUNNEL_LEAD = funnel-lead).
PageName
Key: pageName. Type: string. Required. This property is the contextual title for whatever page the event is triggered on. The data team should specify the value for this property, or use document.title
as a failsafe.
Content
Key: content. Type object. Optional. This property should be a single level object (no nested objects/values) with all values being of type string
(comma-separated list if multiple values). Example:
const content = {
"insurance-provider": "insurance-company",
"insurance-plan": "insurance-plan-type",
"dental-concerns": "whiter teeth, gingivitis, plaque"
};
This library will throw an error if you pass key:value
pairs that aren't string:string
. When data requests an event, this will look like [key: value, key: value, ...]
. Treat their array as an object when implementing.
Name
Key: name. Type: string. Optional. This property is to help categorize the feature this event is related to. The data team should supply this.
Section
Key: section. Type: string. Optional. This property is to help define the part of the feature this event is related to. The data team should supply this.
Position
Key: position. Type: array. Optional. This property is an array of numbers, and is to help define where the element this event is being called on is in relation to other like elements. e.g. Capturing the fourth profile card in a list of match results would be position: [4]
, or a multi-select step in the funnel would be position: [3, 5, 6]
for the indexes of selected options.
UserId
Key: userId. Type: number. Optional. This property is the user ID from Opencare API when the user has an account.
An important note! If you set this property, please also clear it when the user logs out. You can clear this by calling OpencareAnalytics.clearUserId();
This is the only parameter that requires you to call a clearing method on logout.
PatientId
Key: patientId. Type: number. Optional. This property is the patient ID from Opencare API when the user has an account.
ProviderId
Key: providerId. Type: number. Optional. This property is the provider ID from Opencare API. Note doctor ID and provider ID are different.
PracticeId
Key: practiceId. Type: number. Optional. This property is the practice ID from Opencare API.
LeadId
Key: leadId. Type: string. Optional. This property is a generated lead ID when submitting a Lead Form in our landing pages.
DoctorId
Key: doctorId. Type: number. Optional. This property is the doctor ID from Opencare API. Note doctor ID and provider ID are different.
PartnerId
Key: partnerId. Type: number. Optional. This property is the partner ID from Opencare API.
UserSuppliedLocation
Key: userSuppliedLocation. Type: object. Optional. This property is to track the user specified location - aka the location they give at the start of the funnel. It needs to be an object like:
{
country: "Canada", // required
state: "ON", // required
city: "Toronto", // required
street: "180 Dundas St W", // optional, send if supplied
postal: "M5G 1Z8" // optional, send if supplied
}
FunnelConfigId
Key: funnelConfigId. Type: number. Optional. This property is the ID of the funnel configuration a user got.
MatchId
Key: matchId. Type: number. Optional. This property is the match ID from Opencare API when a user completes the funnel.
AppointmentId
Key: appointmentId. Type: number. Optional. This property is the appointment ID from Opencare API when a user books an appointment.
Fullstory
Key: fullStory. Type: object. Optional. This property is to give you the flexibility to set additional user properties in Fullstory. By default, match ID, appointment ID, and patient ID are already set in Fullstory when they exist. For setting additional user properties, use this property. All your key:value pairs will need to match Fullstory's documentation.
Hotjar
Key: hotjar. Type: object. Optional. This property is to give you the flexibility to set additional user properties in Hotjar. Hotjar Documentation.
Additional Methods
clearUserId()
When you send the userId
property with any of the tracking events, we capture it and send it with all subsequent events. When that user logs out, this method allows you to inform us of the change so we can stop tracking their ID.
waitForQueue()
Snowplow uses a LocalStorage item to capture all events locally that haven't been sent in a network request yet. This is safety mechanism to prevent events being lost in-app page navigation. However this queue is only maintained within each app, and doesn't work across domains. This method is to account for the exit points where we'll be sending users to a new app, and want to ensure the queue is empty (all events sent to Snowflake) before sending them.
An important note: this method maxes out at 2.5 seconds, to maintain good user experience.
trackDefaultPageView()
While we have a page view tracking event - trackPageView
, it fundamentally represents the business context of a page. It is a page view event that includes specific pageType
and pageName
(at least) values. However, it's important that we capture every page view - even if we haven't attached business context to it. This method is meant to be called within your app using a listener on the URL. For example in React, this would involve listening to the history
object. This method should only live in a single place in each app (under an event listener on URL changes).
Third Party Integrations
This package manages the integration of third party pixels for you. We're connected to:
- Google Analytics
- Google Ads
- Bing
- Partnerstack (aka Growsumo)
- Fullstory
- Hotjar
- Optimizely (the initialization has been hardcoded to make sure Optimizely's DOM manipulation becomes synchronous)
- Heap
Testing and this package
This package relies heavily on the window and localstorage objects. Furthermore, as it's responsibility is to send analytics events to Snowplow, you should mock it for all your tests. To help with that, we've added a method to this package - OpencareAnalytics.mock()
.
Here's how you can use this mock (this example is specifically for React and Jest):
- Create a
__mocks__/
folder at the same level as yournode_modules/
folder. - Create a file called
analytics-opencare.js
within the__mocks__
folder (The name must match the package name). - In the file you just created, copy and paste the following:
import Analytics from 'analytics-opencare';
module.exports = new Analytics().mock();
Deployment
For most of our apps, this package is imported as a dependecy in package.json
, which means updating to the latest version is as easy as running yarn upgrade analytics-opencare
(or yarn upgrade @bower_components/analytics-opencare
for Angular) in whichever app needs to be updated.
Additionally, this package is hosted on assets.opencare.com (actual route) so it can be included in places like the Content Hub and Unbounce. Running yarn deploy
in this repository will update that hosted file to the latest version.
For testing purposes, here are the locations that current connect to assets.opencare.com/analytics/index.js:
- opencare.com/blog (WP Blog)
- opencare.com/support (Zendesk)
- opencare.com/dentist-guide-to-reopening (static ebook)
Updating Our Custom Schemas
In addition to the default properties and values Snowplow tracks for us, all of our events are setup with additional context that's unique to Opencare. This custom schema is managed outside of this repository. You can view it in this repository, which is made available to Fivetran/Snowplow through an IP whitelisted app - http://elb-opencare-24747.aptible.in/. The IPs that are whitelisted are:
- Fivetran IP addresses
- Our Engineering VPN