From 8c56c523cd2e0038ec8b8058cd56ba41671b409e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Wr=C3=B3blewski?= Date: Tue, 5 Dec 2023 12:17:58 +0300 Subject: [PATCH] =?UTF-8?q?AG-25544=20Improve=20google-analytics=20?= =?UTF-8?q?=E2=80=94=20ga.q.=20#355?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Squashed commit of the following: commit 6a6bdfd25f2a9fdd239c72f54bd12086950fd911 Author: Adam Wróblewski Date: Mon Dec 4 18:59:07 2023 +0100 Simplify forEach commit bfcdcc567b77c19ff4acec2bcbb1f322d66ebda7 Author: Adam Wróblewski Date: Mon Dec 4 18:32:44 2023 +0100 Add ga.q to google-analytics --- CHANGELOG.md | 8 +++++ src/redirects/google-analytics.js | 10 ++++++ tests/redirects/google-analytics.test.js | 40 +++++++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66a690ae..fed9e702 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 +## [Unreleased] + +### Added + +- `ga.q` (queued commands) to `google-analytics` redirect + [#355](https://github.com/AdguardTeam/Scriptlets/issues/355) + ## [v1.9.101] - 2023-11-30 ### Added @@ -308,6 +315,7 @@ prevent inline `onerror` and match `link` tag [#276](https://github.com/AdguardT - `metrika-yandex-tag` [#254](https://github.com/AdguardTeam/Scriptlets/issues/254) - `googlesyndication-adsbygoogle` [#252](https://github.com/AdguardTeam/Scriptlets/issues/252) +[Unreleased]: https://github.com/AdguardTeam/Scriptlets/compare/v1.9.101...HEAD [v1.9.101]: https://github.com/AdguardTeam/Scriptlets/compare/v1.9.96...v1.9.101 [v1.9.96]: https://github.com/AdguardTeam/Scriptlets/compare/v1.9.91...v1.9.96 [v1.9.91]: https://github.com/AdguardTeam/Scriptlets/compare/v1.9.83...v1.9.91 diff --git a/src/redirects/google-analytics.js b/src/redirects/google-analytics.js index 440c77e0..be414991 100644 --- a/src/redirects/google-analytics.js +++ b/src/redirects/google-analytics.js @@ -34,6 +34,8 @@ export function GoogleAnalytics(source) { proto.send = noopFunc; const googleAnalyticsName = window.GoogleAnalyticsObject || 'ga'; + const queue = window[googleAnalyticsName]?.q; + // a -- fake arg for 'ga.length < 1' antiadblock checking // eslint-disable-next-line no-unused-vars function ga(a) { @@ -70,6 +72,14 @@ export function GoogleAnalytics(source) { ga.loaded = true; window[googleAnalyticsName] = ga; + if (Array.isArray(queue)) { + const push = (arg) => { + ga(...arg); + }; + queue.push = push; + queue.forEach(push); + } + const { dataLayer, google_optimize } = window; // eslint-disable-line camelcase if (dataLayer instanceof Object === false) { return; diff --git a/tests/redirects/google-analytics.test.js b/tests/redirects/google-analytics.test.js index 4dd6224a..75be403e 100644 --- a/tests/redirects/google-analytics.test.js +++ b/tests/redirects/google-analytics.test.js @@ -162,7 +162,7 @@ test('Test eventCallback mocking', (assert) => { test('Test .push(data) mocking', (assert) => { // emulate API window.dataLayer = []; - window.dataLayer.push = () => {}; + window.dataLayer.push = () => { }; const gtag = (data) => { window.dataLayer.push(data); }; @@ -234,3 +234,41 @@ test('Test callback mocking', (assert) => { assert.strictEqual(window.hit, 'FIRED', 'hit function was executed'); }); + +test('Test ga queued commands', (assert) => { + let firstScriptExecuted = false; + let secondScriptExecuted = false; + + function gaFunction(...args) { + window.ga.q = window.ga.q || []; + window.ga.q.push(args); + } + + window.ga = window.ga || gaFunction; + + window.ga('create', 'UA-32789052-1', 'auto'); + + window.ga('send', 'pageview', { + page: '/', + hitCallback: () => { + firstScriptExecuted = true; + }, + }); + + window.ga('event', 'pageview', { + page: '/test', + hitCallback: () => { + secondScriptExecuted = true; + }, + }); + + runRedirect(name); + + const done = assert.async(); + + setTimeout(() => { + assert.strictEqual(firstScriptExecuted, true, 'first hitCallback executed'); + assert.strictEqual(secondScriptExecuted, true, 'second hitCallback executed'); + done(); + }, 20); +});