CypressでGoogle Analytics (gtag.jsやGTM)のテストを書く

CypressでGoogle Analyticsによるトラッキングをテストしたいケースがあり、少し苦戦したのでメモしておく。gtag.jsを使うパターンとGTMを使うパターンそれぞれについて触れておく。
※ gtagとGTMの違いはこちら
公式example
Cypressの公式exampleの中にGoogle Analyticsのテストをするものがある。ただ、2022年1月時点ではgtag.jsではなくanalytics.js(旧仕様)が使われた例となっており、そのままgtagに置き換えてもうまく動かなかった(詳細は後述)。
このスクラップでは色々と試した結果、うまく動いた書き方を載せておく。ベストプラクティスかどうかは分からないので、このスクラップにたどり着いた方は、まずは上のexampleを参考にするのが良いと思う。

gtag.jsが正常に読み込まれていることをテストする
まずはgtag.jsのコードが読み込まれていることを確認する。これはさほど難しくなく、window
オブジェクトからdataLayer
やgtag
といったプロパティを呼び出せることをテストすればOK。
it('gtag.jsが読み込まれていること', () => {
cy.visit('/');
cy.window().then((window: any) => {
assert.isDefined(window.dataLayer);
assert.isDefined(window.gtag);
});
});

gtag()
が呼び出されることをテストする
特定の引数で例えばページの読み込み後に以下の処理が呼び出されることをテストしたいとする。
window.gtag(
'config',
'G-12345678',
{
cookie_domain: 'none',
cookie_prefix: 'example',
cookie_expires: 86400,
}
);
これは(ベストの書き方か分からないが)以下のような書き方でテストできる。
it('gtag("config")が呼び出されること', () => {
cy.visit('/');
cy.window().then((window: any) => {
window.gtag = cy.stub().as('gtag'); // gtag()をスタブする
cy.get('@gtag').should(
'be.calledWith',
'config',
'G-12345678',
Cypress.sinon.match({
cookie_domain: 'none',
cookie_prefix: 'example',
cookie_expires: 86400,
})
);
});
});
同様の書き方でgtag('event', ...)
によりイベントのトラッキングをテストすること等も可能。
公式のexampleの通りに書いても動かなかった部分とその対応について
-
公式のexampleでは
cy.window()
は使われていないが、どうしてもgtag()
の発火を捕捉できなかったためcy.window()
を使うことにした。 - 公式exampleでは
Cypress.on('window:before:load', () => { ... })
の中でスタブしているが、cy.window()
を使うとスタブが効かないため、cy.window().then(() => { ... })
の中でスタブすることにした。
補足
-
window.gtag = cy.stub().as('gtag')
について: Cypressではのようにオブジェクトに対してas
でエイリアス名を定義するとget(@エイリアス名)
という形でオブジェクトを参照できるようになる(参考)。 -
Cypress.sinon.match
について:Cypress.sinon.○○
という書き方をすることでSinon.JSのマッチャを使える。

GTMのhistory change triggerをテストする
GTMでのトラッキングをCypressでテストする方法についてもメモしておく。
GTMではトラッキング設定でHistory Changeに基づくトリガーを設定できる。これによりSPAなどでクライアントサイドでページ遷移された時にもページビューが記録される。
History change triggerによるトラッキングが行われていることをテストする
historyChangeベースのトラッキングが行われた場合、window.dataLayer
の配列の中に { event: "gtm.historyChange-v2", ... }
というオブジェクトが追加される模様。Cypressでページ遷移をした後にこのオブジェクトが存在することを確認してみる。
it('GTMでhistory changeによるトラッキングが行われている', () => {
cy.visit('/');
cy.get('a[href="/foo"]').click(); // fooページに遷移する
cy.wait(3000); // `window.dataLayer`が更新されるまで少し待つ必要がある
cy.window().then((window: any) => {
assert.isTrue(
window.dataLayer.some(
(key: any) => key.event === 'gtm.historyChange-v2'
)
);
});
});
そもそもこのテストをCypressで書くべきなのか?(or 書く必要があるのか?)というのは微妙なところだが。