Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Botonic Plugin Google Analytics #823

Merged
merged 16 commits into from
Jul 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
19242d9
chore(plugin-google-analytics): add basic tracking to Google Analytic…
asastre Jun 17, 2020
8be257f
docs(plugin-google-analytics): add Readme file
asastre Jun 17, 2020
151da84
refactor(plugin-google-analytics): remove async/await and refactor th…
asastre Jun 18, 2020
2131e79
chore(plugin-google-analytics): correct version packages to be more c…
asastre Jun 18, 2020
7b340ef
docs(plugin-google-analytics): enhance and correct the documentation
asastre Jun 18, 2020
7439e14
chore(plugin-google-analytics): add pre commit/push configurations
asastre Jun 18, 2020
fb421c5
feat(plugin-google-analytics): add user identification while tracking…
asastre Jun 19, 2020
19af4c5
docs(plugin-google-analytics): adapt documentation to new features
asastre Jun 19, 2020
8615719
fix(plugin-google-analytics): fix pre-commit config
asastre Jun 19, 2020
9cf8e24
refactor(plugin-google-analytics): change defaultUserId and defaultUs…
asastre Jun 19, 2020
712903e
feat(plugin-google-analytics): add the eventFields option to enable c…
asastre Jun 19, 2020
c9f9751
refactor(plugin-google-analytics): change trackManually option to aut…
asastre Jun 19, 2020
5f21074
refactor(plugin-google-analytics): refactor options.userId, options.u…
asastre Jun 19, 2020
aa21d1a
feat(plugin-google-analytics): remove default userId/userTraits and d…
asastre Jun 20, 2020
1ff8979
feat(plugin-google-analytics): replace tracking through analytics lib…
asastre Jun 25, 2020
355a10b
refactor(plugin-google-analytics): refactor assignment of cid and uid
asastre Jul 1, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/botonic-plugin-google-analytics-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Botonic plugin-google-analytics tests

on: [push]

jobs:
botonic-plugin-google-analytics-tests:
name: Botonic plugin-google-analytics tests
runs-on: ubuntu-latest
steps:
- name: Checking out to current branch (Step 1 of 6)
uses: actions/checkout@v1
- name: Setting up node (Step 2 of 6)
uses: actions/setup-node@v1
with:
node-version: '12'
- name: Setting up cache (Step 3 of 6)
uses: actions/cache@v1
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install botonic-plugin-google-analytics (Step 4 of 6)
run: (cd ./packages/botonic-plugin-google-analytics && npm install -D)
- name: Install common packages dependencies (Step 5 of 6)
run: npm install -D
- name: Verify lint botonic-plugin-google-analytics (Step 6 of 6)
run: (cd ./packages/botonic-plugin-google-analytics && npm run lint_ci)
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,9 @@ repos:
language: system
files: ^packages/botonic-react/

- id: google-analytics
name: google-analytics
entry: scripts/qa/lint-package.sh packages/botonic-plugin-google-analytics
language: system
files: ^packages/botonic-plugin-google-analytics/

57 changes: 57 additions & 0 deletions packages/botonic-plugin-google-analytics/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Botonic Plugin Google Analytics

## What Does This Plugin Do?

With this plugin you can track the user interaction with the bot or the bot's behaviour sending the information to [Google Analytics](https://analytics.google.com/).

## Setup

1. Run `npm install --save @botonic/plugin-google-analytics` to install the plugin.
2. Add it to the `src/plugins.js` file:

**src/plugins.js**
```javascript
export const plugins = [
{
id: 'google_analytics',
resolve: require('@botonic/plugin-google-analytics'),
options: {
trackingId: 'UA-XXXXXXXX-Y', // Your Google Analytics tracking ID
getUserId: ({session}) => session.user.extra_data.analyticsUserId, //Optional. Method that returns a unique user ID as string
getUserTraits: ({session}) => { userName: session.user.extra_data.analyticsUserName, userEmail: session.user.extra_data.analyticsUserEmail }, //Optional. Method that returns an object with the user Traits
automaticTracking: true, //Optional. Indicates if an automatic tracking will be executed on every user interaction (true by default)
getEventFields: () => ({category: 'bot', action: 'user_interaction'}) //Optional. Set custom event fields to track if automatic tracking is enabled
}
}
]
```
If no `getUserId` is set, the plugin will not identify the userId (logged user) to Google Analytics. The clientId will be sent either way in all trackings. (see [clientId vs. userId](https://support.google.com/analytics/answer/6205850?hl=en#clientid-userid) for more information).
The user traits (`getUserTraits`) will be sent only if `getUserId` is set.
If `automaticTracking` is set to `false`, the plugin will not track automatically in every user interaction.
If no `getEventFields` is set, the plugin will send a default set of fields to the automatic tracking. This option is used only if `automaticTracking` is not set or is set to `true`.

## Use

This plugin can also be used to track manually.
The tracking must be done inside the `botonicInit` method and make sure to call it with the `await` keyword to ensure its execution.
For every tracking, the user will be identified with the `userId` and `userTraits` defined in the plugin's options or with its default values.

`eventFields` contains these Google Analytic [event tracking fields](https://developers.google.com/analytics/devguides/collection/analyticsjs/events#event_fields) :
- `category`: eventCategory in Google Analytics (string, required)
- `action`: eventAction in Google Analytics (string, required)
- `label`: eventLabel in Google Analytics (string, optional)
- `value`: eventValue in Google Analytics (numeric, optional)
```javascript
static async botonicInit({ input, session, params, lastRoutePath, plugins }) {
const ga = plugins.google_analytics

const eventFields = {
category: 'chatbot',
asastre marked this conversation as resolved.
Show resolved Hide resolved
action: 'user_message_sent',
label: 'rating',
value: 4
}

await ga.track({ session, eventFields })
}
```
42 changes: 42 additions & 0 deletions packages/botonic-plugin-google-analytics/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions packages/botonic-plugin-google-analytics/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "@botonic/plugin-google-analytics",
"version": "0.14.0",
asastre marked this conversation as resolved.
Show resolved Hide resolved
"main": "src/index.js",
"scripts": {
"cloc": "../../scripts/qa/cloc-package.sh .",
"prepare": "node ../../preinstall.js",
"lint": "npm run lint_core -- --fix",
"lint_ci": "npm run lint_core",
asastre marked this conversation as resolved.
Show resolved Hide resolved
"lint_core": "../../node_modules/.bin/eslint_d --cache --quiet 'src/**/*.js'"
},
"dependencies": {
"axios": "^0.19.2",
"uuid": "^8.2.0"
},
"devDependencies": {}
}
75 changes: 75 additions & 0 deletions packages/botonic-plugin-google-analytics/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import axios from 'axios'
import { v4 as uuidv4 } from 'uuid'

export default class BotonicPluginGoogleAnalytics {
GA_URL = 'https://www.google-analytics.com/collect'
GA_API_VERSION = '1'

/**
* @param {Object} options - Options for the plugin
* @param {string} options.trackingId - Tracking ID for Google Analytics.
* @param {function({session: object}): string} [options.getClientId] - Method that returns the Google Analytics Client Id from browser.
* @param {function({session: object}): string} [options.getUserId] - Method that returns a unique user ID as string.
* @param {boolean} [options.automaticTracking] - If set to false, no automatic tracking will be done in post method.
* @param {function({session: object, input: object, lastRoutePath: string}): object} [options.getEventFields] - Method
* that returns the eventFields to track as object (used only if automaticTracking is not set or set to true).
*/
constructor(options) {
this.trackingId = options.trackingId
this.getGaClientId = options.getClientId
this.getUserId = options.getUserId
this.getEventFields = options.getEventFields ?? this.defaultGetEventFields
this.automaticTracking = options.automaticTracking ?? true
}

async pre({ input, session, lastRoutePath }) {}

async post({ input, session, lastRoutePath, response }) {
if (this.automaticTracking) {
await this.track({
session,
eventFields: this.getEventFields({ session, input, lastRoutePath }),
})
}
}

defaultGetEventFields = ({ session, input, lastRoutePath }) => ({
category: session.bot.name,
action: lastRoutePath,
label: input.data,
})

/**
* Track event to Google Analytics
* @param {Object} session - Bot's session
* @param {Object} eventFields - Event fields to send (see https://developers.google.com/analytics/devguides/collection/analyticsjs/events#event_fields)
* @param {string} eventFields.category - Google Analytics eventCategory field
* @param {string} eventFields.action - Google Analytics eventAction field
* @param {string} [eventFields.label] - Google Analytics eventLabel field
* @param {number} [eventFields.value] - Google Analytics eventValue field
* @returns {Promise}
*/
async track({ session, eventFields }) {
if (!eventFields.category || !eventFields.action)
throw new Error(
'The eventFields object must contain the fields: category (ec) and action (ea)'
)

const params = {
v: this.GA_API_VERSION,
tid: this.trackingId,
t: 'event',
ec: eventFields.category,
ea: eventFields.action,
el: eventFields.label,
ev: eventFields.value,
}
const cid = this.getGaClientId && this.getGaClientId({ session })
params.cid = cid ?? uuidv4()

const uid = this.getUserId && this.getUserId({ session })
if (uid) params.uid = uid

return await axios.get(this.GA_URL, { params })
}
}