From 9a854ec09895a27f81004bfc1affdb649feaaf33 Mon Sep 17 00:00:00 2001 From: zhanzhao Date: Tue, 2 Aug 2022 20:43:52 +0800 Subject: [PATCH] feat: add Google Analytics 4 (GA4) gtag.js plugin (#1695) --- build/build.js | 1 + docs/plugins.md | 38 ++++++++++---- src/plugins/ga.js | 52 ++++--------------- src/plugins/gtag.js | 72 +++++++++++++++++++++++++++ test/e2e/{ga.test.js => gtag.test.js} | 34 ++++++------- 5 files changed, 128 insertions(+), 69 deletions(-) create mode 100644 src/plugins/gtag.js rename test/e2e/{ga.test.js => gtag.test.js} (74%) diff --git a/build/build.js b/build/build.js index 0de786828..91155512a 100644 --- a/build/build.js +++ b/build/build.js @@ -80,6 +80,7 @@ async function buildAllPlugin() { var plugins = [ {name: 'search', input: 'search/index.js'}, {name: 'ga', input: 'ga.js'}, + {name: 'gtag', input: 'gtag.js'}, {name: 'matomo', input: 'matomo.js'}, {name: 'emoji', input: 'emoji.js'}, {name: 'external-script', input: 'external-script.js'}, diff --git a/docs/plugins.md b/docs/plugins.md index 1c538d049..dce1f4e64 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -71,18 +71,42 @@ This plugin ignores diacritical marks when performing a full text search (e.g., ## Google Analytics +> Google's Universal Analytics service will no longer process new data in standard properties beginning July 1, 2023. Prepare now by setting up and switching over to a Google Analytics 4 property and docsify's gtag.js plugin. + Install the plugin and configure the track id. ```html + + +``` + +Configure by `data-ga`. + + +```html + + +``` + +## Google Analytics 4 (GA4) + +Install the plugin and configure the track id. + +```html + - -``` - -Configure by `data-ga`, only support single gtag. - - -```html - - + ``` ## Emoji diff --git a/src/plugins/ga.js b/src/plugins/ga.js index 8f0e42e22..37167a4dc 100644 --- a/src/plugins/ga.js +++ b/src/plugins/ga.js @@ -1,48 +1,22 @@ /* eslint-disable no-console */ // From https://github.com/egoist/vue-ga/blob/master/src/index.js - -function appendScript(id) { +function appendScript() { const script = document.createElement('script'); script.async = true; - script.src = 'https://www.googletagmanager.com/gtag/js?id=' + id; + script.src = 'https://www.google-analytics.com/analytics.js'; document.body.appendChild(script); } -// global site tag instance initialized -function initGlobalSiteTag(id) { - appendScript(id); - - window.dataLayer = window.dataLayer || []; - window.gtag = - window.gtag || +function init(id) { + appendScript(); + window.ga = + window.ga || function () { - window.dataLayer.push(arguments); + (window.ga.q = window.ga.q || []).push(arguments); }; - window.gtag('js', new Date()); - window.gtag('config', id); -} - -// add additional products to your tag -// https://developers.google.com/tag-platform/gtagjs/install -function initAdditionalTag(id) { - window.gtag('config', id); -} - -function init(ids) { - if (Array.isArray(ids)) { - // set the first id to be a global site tag - initGlobalSiteTag(ids[0]); - - // the rest ids - ids.forEach((id, index) => { - if (index > 0) { - initAdditionalTag(id); - } - }); - } else { - initGlobalSiteTag(ids); - } + window.ga.l = Number(new Date()); + window.ga('create', id, 'auto'); } function collect() { @@ -50,12 +24,8 @@ function collect() { init($docsify.ga); } - // usage: https://developers.google.com/analytics/devguides/collection/gtagjs/pages - window.gtag('event', 'page_view', { - page_title: document.title, - page_location: location.href, - page_path: location.pathname, - }); + window.ga('set', 'page', location.hash); + window.ga('send', 'pageview'); } const install = function (hook) { diff --git a/src/plugins/gtag.js b/src/plugins/gtag.js new file mode 100644 index 000000000..aec713cb7 --- /dev/null +++ b/src/plugins/gtag.js @@ -0,0 +1,72 @@ +/* eslint-disable no-console */ +// From ./ga.js + +function appendScript(id) { + const script = document.createElement('script'); + script.async = true; + script.src = 'https://www.googletagmanager.com/gtag/js?id=' + id; + document.body.appendChild(script); +} + +// global site tag instance initialized +function initGlobalSiteTag(id) { + appendScript(id); + + window.dataLayer = window.dataLayer || []; + window.gtag = + window.gtag || + function () { + window.dataLayer.push(arguments); + }; + + window.gtag('js', new Date()); + window.gtag('config', id); +} + +// add additional products to your tag +// https://developers.google.com/tag-platform/gtagjs/install +function initAdditionalTag(id) { + window.gtag('config', id); +} + +function init(ids) { + if (Array.isArray(ids)) { + // set the first id to be a global site tag + initGlobalSiteTag(ids[0]); + + // the rest ids + ids.forEach((id, index) => { + if (index > 0) { + initAdditionalTag(id); + } + }); + } else { + initGlobalSiteTag(ids); + } +} + +function collect() { + if (!window.gtag) { + init($docsify.gtag); + } + + // usage: https://developers.google.com/analytics/devguides/collection/gtagjs/pages + window.gtag('event', 'page_view', { + /* eslint-disable camelcase */ + page_title: document.title, + page_location: location.href, + page_path: location.pathname, + /* eslint-disable camelcase */ + }); +} + +const install = function (hook) { + if (!$docsify.gtag) { + console.error('[Docsify] gtag is required.'); + return; + } + + hook.beforeEach(collect); +}; + +$docsify.plugins = [].concat(install, $docsify.plugins); diff --git a/test/e2e/ga.test.js b/test/e2e/gtag.test.js similarity index 74% rename from test/e2e/ga.test.js rename to test/e2e/gtag.test.js index c021eaa9f..c3ebbcd18 100644 --- a/test/e2e/ga.test.js +++ b/test/e2e/gtag.test.js @@ -1,10 +1,10 @@ // Modules, constants, and variables -// npm run test:e2e ga.test.js +// npm run test:e2e gtag.test.js // ----------------------------------------------------------------------------- const docsifyInit = require('../helpers/docsify-init'); const { test, expect } = require('./fixtures/docsify-init-fixture'); -const gaTagList = [ +const gtagList = [ 'AW-YYYYYY', // Google Ads 'DC-ZZZZZZ', // Floodlight 'G-XXXXXX', // Google Analytics 4 (GA4) @@ -13,14 +13,14 @@ const gaTagList = [ // Suite // ----------------------------------------------------------------------------- -test.describe('GA Plugin Tests', () => { +test.describe('Gtag Plugin Tests', () => { // page request listened, print collect url function pageRequestListened(page) { - // page.on('request', request => { - // if (request.url().indexOf('www.google-analytics.com') !== -1) { - // console.log(request.url()); - // } - // }); + page.on('request', request => { + if (request.url().indexOf('www.google-analytics.com') !== -1) { + // console.log(request.url()); + } + }); page.on('response', response => { const request = response.request(); @@ -30,7 +30,7 @@ test.describe('GA Plugin Tests', () => { const reg = /googleads\.g\.doubleclick\.net|www\.google-analytics\.com|www\.googletagmanager\.com/g; if (request.url().match(reg)) { - console.log(request.url(), response.status()); + // console.log(request.url(), response.status()); } }); } @@ -42,9 +42,9 @@ test.describe('GA Plugin Tests', () => { const docsifyInitConfig = { config: { - ga: gaTagList[0], + gtag: gtagList[0], }, - scriptURLs: ['/lib/plugins/ga.min.js'], + scriptURLs: ['/lib/plugins/gtag.min.js'], styleURLs: ['/lib/themes/vue.css'], }; @@ -57,10 +57,10 @@ test.describe('GA Plugin Tests', () => { // Verify config options expect(typeof $docsify).toEqual('object'); - console.log($docsify.ga, $docsify.ga === ''); + // console.log($docsify.gtag, $docsify.gtag === ''); // Tests - expect($docsify.ga).not.toEqual(''); + expect($docsify.gtag).not.toEqual(''); }); test('multi gtag', async ({ page }) => { @@ -68,9 +68,9 @@ test.describe('GA Plugin Tests', () => { const docsifyInitConfig = { config: { - ga: gaTagList, + gtag: gtagList, }, - scriptURLs: ['/lib/plugins/ga.min.js'], + scriptURLs: ['/lib/plugins/gtag.min.js'], styleURLs: ['/lib/themes/vue.css'], }; @@ -83,10 +83,10 @@ test.describe('GA Plugin Tests', () => { // Verify config options expect(typeof $docsify).toEqual('object'); - console.log($docsify.ga, $docsify.ga === ''); + // console.log($docsify.gtag, $docsify.gtag === ''); // Tests - expect($docsify.ga).not.toEqual(''); + expect($docsify.gtag).not.toEqual(''); }); test('data-ga attribute', async ({ page }) => {