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

feat(plugin): add support for Google Analytics 4 (gtag) #138

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
[![@nuxtjs/google-analytics](https://google-analytics.nuxtjs.org/preview.png)](https://google-analytics.nuxtjs.org)


> **⚠ WARNING: This package does not support GA4. **
> This package currently only supports GA3/UA

# @nuxtjs/google-analytics

[![npm version][npm-version-src]][npm-version-href]
Expand All @@ -12,7 +8,7 @@
[![Codecov][codecov-src]][codecov-href]
[![License][license-src]][license-href]

> [Google Analytics](https://analytics.google.com/analytics/web/) integration for [Nuxt](https://nuxtjs.org) using [vue-analytics](https://github.com/MatteoGabriele/vue-analytics).
> [Google Analytics](https://analytics.google.com/analytics/web/) integration for [Nuxt](https://nuxtjs.org) using [vue-analytics](https://github.com/MatteoGabriele/vue-analytics) for Google Analytics 3 and [vue-gtag](https://github.com/MatteoGabriele/vue-gtag) for Google Analytics 4.

- [✨  Release Notes](./CHANGELOG.md)
- [📖  Documentation](https://google-analytics.nuxtjs.org)
Expand Down
2 changes: 1 addition & 1 deletion docs/content/en/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ features:
<img src="/preview.png" class="light-img" width="1280" height="640" alt=""/>
<img src="/preview-dark.png" class="dark-img" width="1280" height="640" alt=""/>

[Google Analytics](https://analytics.google.com/analytics/web/) integration for [Nuxt](https://nuxtjs.org) using [vue-analytics](https://github.com/MatteoGabriele/vue-analytics).
[Google Analytics](https://analytics.google.com/analytics/web/) integration for [Nuxt](https://nuxtjs.org) using [vue-analytics](https://github.com/MatteoGabriele/vue-analytics) for Google Analytics 3 and [vue-gtag](https://github.com/MatteoGabriele/vue-gtag) for Google Analytics 4.

Track the visitors to your sites and applications, measure your ROI and provide in-depth analysis details about your visitors' behaviors.

Expand Down
54 changes: 53 additions & 1 deletion docs/content/en/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,24 @@ If both `id` and `asyncID` are present, the returned value from `asyncID` will o

</alert>


### `useGtag`

* Type: `Boolean`
* default: `false`

If set to `true`, the module will use [Google Analytics 4](#google-analytics-4). By default, the module uses [Google Analytics 3](#google-analytics-3). Refer to the respective sections for options below.

## Google Analytics 3

The following options are only applicable if you have `useGtag` set to false.

<alert type="info">

For a full list of options, please see [Vue Analytics](https://matteogabriele.gitbooks.io/vue-analytics) documentation.

</alert>

### `debug`

* Type: `Object`
Expand Down Expand Up @@ -110,8 +128,42 @@ export default {
}
```

## Google Analytics 4

The following options are only applicable if you have `useGtag` set to true.

<alert type="info">

For a full list of options, please see [Vue Analytics](https://matteogabriele.gitbooks.io/vue-analytics) documentation.
For a full list of options, please see [Vue Gtag v1](https://matteo-gabriele.gitbook.io/vue-gtag/v/master/) documentation.

</alert>

### `disableScriptLoad`

* Type: `Boolean`

Disable the script loader

```js[nuxt.config.js]
export default {
googleAnalytics: {
disableScriptLoad: true
}
}
```

### `onReady`

* Type: `Function`

Will fire when the gtag script is successfully loaded

```js[nuxt.config.js]
export default {
googleAnalytics: {
onReady() {
// Ready!
}
}
}
```
5 changes: 3 additions & 2 deletions docs/content/en/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ category: Guide
---


> **⚠ WARNING: This package does not support GA4. **
> This package currently only supports GA3/UA
<alert type="warning">
If you need Google Analytics 4 support, check our documentation on the `useGtag` option <nuxt-link to="/options#usegtag">here</nuxt-link>
</alert>


Check the [Nuxt.js documentation](https://nuxtjs.org/guides/configuration-glossary/configuration-modules) for more information about installing and using modules in Nuxt.js.
Expand Down
4 changes: 4 additions & 0 deletions docs/content/en/usage/event-tracking.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ position: 5
category: Usage
---

<alert type="warning">
This documentation is only applicable when the Google Analytics 3 is enabled. For documentation on event tracking with Google Analytics 4, see <a href="https://matteo-gabriele.gitbook.io/vue-gtag/v/master/methods/events">vue-gtag/event documentation</a>.
</alert>

This module injects `$ga` instance globally.

You can access the instance anywhere using:
Expand Down
4 changes: 4 additions & 0 deletions docs/content/en/usage/page-tracking.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ position: 4
category: Usage
---

<alert type="warning">
This documentation is only applicable when the Google Analytics 3 is enabled. For documentation on event tracking with Google Analytics 4, see <a href="https://matteo-gabriele.gitbook.io/vue-gtag/v/master/methods/pageview">vue-gtag/pageview documentation</a>.
</alert>

This module injects `$ga` instance globally. You can access the instance anywhere using `this.$ga` (within a component), or `context.$ga` (for plugins, `asyncData`, `fetch`, `nuxtServerInit` ,and middleware)

## Automatic page tracking
Expand Down
4 changes: 4 additions & 0 deletions docs/content/en/usage/screen-tracking.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ position: 6
category: Usage
---

<alert type="warning">
This documentation is only applicable when the Google Analytics 3 is enabled. For documentation on event tracking with Google Analytics 4, see <a href="https://matteo-gabriele.gitbook.io/vue-gtag/v/master/methods/screenviews">vue-gtag/screenview documentation</a>.
</alert>

This module injects `$ga` instance globally. You can access the instance anywhere using `this.$ga` (within a component), or `context.$ga` (for plugins, `asyncData`, `fetch`, `nuxtServerInit` ,and middleware)

## `screenview(options)`
Expand Down
4 changes: 4 additions & 0 deletions docs/content/en/usage/time-tracking.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ position: 7
category: Usage
---

<alert type="warning">
This documentation is only applicable when the Google Analytics 3 is enabled. For documentation on event tracking with Google Analytics 4, see <a href="https://matteo-gabriele.gitbook.io/vue-gtag/v/master/methods/time">vue-gtag/time documentation</a>.
</alert>

This module injects `$ga` instance globally. You can access the instance anywhere using `this.$ga` (within a component), or `context.$ga` (for plugins, `asyncData`, `fetch`, `nuxtServerInit` ,and middleware)

## `time()`
Expand Down
14 changes: 10 additions & 4 deletions lib/plugin.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Vue from 'vue'
import VueAnalytics from 'vue-analytics'
import VueGtag from 'vue-gtag'

export default async (ctx, inject) => {
const runtimeConfig = ctx.$config && ctx.$config.googleAnalytics || {}
Expand All @@ -10,8 +11,13 @@ export default async (ctx, inject) => {
options.id = await options.asyncID(ctx)
}

Vue.use(VueAnalytics, {...{ router: ctx.app.router }, ...options})

ctx.$ga = Vue.$ga
inject('ga', Vue.$ga)
if (options.useGtag) {
Vue.use(VueGtag, { config: { id: options.id }, ...options }, ctx.app.router)
ctx.$gtag = Vue.$gtag
inject('gtag', Vue.$gtag)
} else {
Vue.use(VueAnalytics, { router: ctx.app.router, ...options})
ctx.$ga = Vue.$ga
inject('ga', Vue.$ga)
}
}
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
"test": "yarn lint && jest"
},
"dependencies": {
"vue-analytics": "^5.22.1"
"vue-analytics": "^5.22.1",
"vue-gtag": "^1.16.1"
},
"devDependencies": {
"@commitlint/cli": "latest",
"@commitlint/config-conventional": "latest",
"@nuxt/types": "^2.15.8",
"@nuxtjs/eslint-config": "latest",
"@nuxtjs/module-test-utils": "latest",
"eslint": "latest",
Expand Down
10 changes: 10 additions & 0 deletions test/fixture/gtag/nuxt.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
rootDir: __dirname,
buildModules: [
{ handler: require('../../../') }
],
googleAnalytics: {
id: 'XXX',
useGtag: true
}
}
11 changes: 11 additions & 0 deletions test/fixture/gtag/pages/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<div>
Works!
</div>
</template>

<script>
export default {
}
</script>
42 changes: 42 additions & 0 deletions test/gtag.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const { setup, loadConfig, get, url } = require('@nuxtjs/module-test-utils')

describe('prod', () => {
let nuxt, addTemplate

beforeAll(async () => {
const beforeNuxtReady = (nuxt) => {
addTemplate = nuxt.moduleContainer.addTemplate = jest.fn(
nuxt.moduleContainer.addTemplate
)
}
({ nuxt } = (await setup(loadConfig(__dirname, 'gtag'), { beforeNuxtReady })))
}, 60000)

afterAll(async () => {
await nuxt.close()
})

test('render', async () => {
const html = await get('/')
expect(html).toContain('Works!')
})

test('$gtag should be defined', async () => {
const window = await nuxt.renderAndGetWindow(url('/'))
expect(window.$nuxt.$gtag).toBeDefined()
})

test('$ga should not be defined', async () => {
const window = await nuxt.renderAndGetWindow(url('/'))
expect(window.$nuxt.$ga).not.toBeDefined()
})

test('option id', () => {
expect(addTemplate).toBeDefined()
const call = addTemplate.mock.calls.find(args => args[0].src.includes('plugin.js'))
expect(call).toBeDefined()
const options = call[0].options
expect(options.id).toBe('XXX')
expect(options.useGtag).toBe(true)
})
})
48 changes: 40 additions & 8 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,65 @@
import type Vue from 'vue'
import type { default as VueAnalytics, InstallOptions } from 'vue-analytics'
import { Module, Context } from '@nuxt/types'
import VueAnalytics, { InstallOptions } from 'vue-analytics'
import { VueGtag, PluginOptions } from 'vue-gtag'
import './vuex'

interface BaseOptions {
id?: string
asyncID?: (context: Context) => Promise<string>
/**
* @deprecated use id instead
*/
ua?: string
useGtag?: boolean
}

interface VueAnalyticsOptions extends BaseOptions, Omit<InstallOptions, 'id'> {
useGtag?: false
}

interface VueGtagOptions extends BaseOptions, Omit<PluginOptions, 'config'> {
useGtag: true
}

type Options = VueAnalyticsOptions | VueGtagOptions

declare module '@nuxt/vue-app' {
interface Context {
$ga: VueAnalytics
$ga?: VueAnalytics
$gtag?: VueGtag
}

interface NuxtAppOptions {
$ga: VueAnalytics
$ga?: VueAnalytics
$gtag?: VueGtag
}
}

// Nuxt 2.9+
declare module '@nuxt/types' {
interface Context {
$ga: VueAnalytics
$ga?: VueAnalytics
$gtag?: VueGtag
}

interface NuxtAppOptions {
$ga: VueAnalytics
$ga?: VueAnalytics
$gtag?: VueGtag
}

interface Configuration {
googleAnalytics?: InstallOptions
googleAnalytics?: Options
}
}

declare module 'vue/types/vue' {
interface Vue {
$ga: VueAnalytics
// @ts-expect-error vue-analytics marks this object as required
$ga?: VueAnalytics
// @ts-expect-error vue-gtag marks this object as required
$gtag?: VueGtag
}
}

declare const analyticsModule: Module<Options>
export default analyticsModule
6 changes: 4 additions & 2 deletions types/vuex.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type VueAnalytics from 'vue-analytics'
import VueAnalytics from 'vue-analytics'
import VueGtag from 'vue-gtag'

declare module 'vuex' {
interface Store<S> {
$ga: VueAnalytics,
$ga?: VueAnalytics
$gtag?: VueGtag
}
}
Loading