<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>計測 on Marketechlabo</title><link>https://www.marketechlabo.com/tags/measurement/</link><description>Recent content in 計測 on Marketechlabo</description><generator>Hugo -- gohugo.io</generator><language>ja-jp</language><lastBuildDate>Thu, 07 Nov 2024 00:00:00 +0900</lastBuildDate><atom:link href="https://www.marketechlabo.com/tags/measurement/index.xml" rel="self" type="application/rss+xml"/><item><title>URLの指定の仕方</title><link>https://www.marketechlabo.com/web-measurement/specify-url/</link><pubDate>Mon, 17 Jun 2019 00:00:00 +0900</pubDate><guid>https://www.marketechlabo.com/web-measurement/specify-url/</guid><description>
&lt;h2 id="javascriptでurlを表すlocationオブジェクト"&gt;JavaScriptでURLを表すlocationオブジェクト&lt;/h2&gt;
&lt;p&gt;URLとそのパーツはJavaScriptの変数として取得できる。&lt;/p&gt;
&lt;p&gt;タグマネージャなどでJavaScriptの変数を使ってURL（の一部）を指定する場合や、直接Javascriptを書いてURLを指定する場合にこれらを使うことがある。&lt;/p&gt;
&lt;p&gt;URLの構造については&lt;a href="url-structure-for-marketer/"&gt;URLと向き合う必要性&lt;/a&gt;を参照。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;変数名&lt;/th&gt;
&lt;th&gt;意味&lt;/th&gt;
&lt;th&gt;例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;window.location.href&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;URL全体&lt;/td&gt;
&lt;td&gt;&lt;a href="https://example.com/audio/detail.php?id=123#rev"&gt;https://example.com/audio/detail.php?id=123#rev&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;window.location.protocol&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;プロトコル&lt;/td&gt;
&lt;td&gt;https:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;window.location.hostname&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ホスト名&lt;/td&gt;
&lt;td&gt;example.com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;window.location.port&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ポート番号（デフォルトポートの場合は空文字）&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;window.location.pathname&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;パス名&lt;/td&gt;
&lt;td&gt;/audio/detail.php&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;window.location.search&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;クエリ文字列&lt;/td&gt;
&lt;td&gt;?id=123&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;window.location.hash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ハッシュ&lt;/td&gt;
&lt;td&gt;#rev&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;（「window.」は省略可）&lt;/p&gt;
&lt;p&gt;たとえば&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;location&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;hostname&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;indexOf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;example.com&amp;#39;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/\/detail\.html$/&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;test&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;location&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;pathname&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// マッチしたときの処理。以下は外部スクリプトファイルを読み込む例
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; document.&lt;span style="color:#a6e22e"&gt;createElement&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;script&amp;#39;&lt;/span&gt;); &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;//js/lib.js&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; document.&lt;span style="color:#a6e22e"&gt;getElementsByTagName&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;script&amp;#39;&lt;/span&gt;)[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;parentNode&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;insertBefore&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;location.hostname.indexOf('example.com') &amp;gt; -1&lt;/code&gt;でホスト名に「example.com」を含み、&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/\/detail\.html$/.test(location.pathname)&lt;/code&gt;でパス名が「/detail.html」で終わる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;URLを指定している。&lt;/p&gt;
&lt;h2 id="参考正規表現"&gt;（参考）正規表現&lt;/h2&gt;
&lt;p&gt;いろいろなパターンの文字列をまとめて指定するものである。&lt;/p&gt;
&lt;h3 id="正規表現の使い道"&gt;正規表現の使い道&lt;/h3&gt;
&lt;p&gt;正規表現を使う処理には&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;マッチするかどうか判定（match）&lt;/li&gt;
&lt;li&gt;マッチした部分の抽出（extract）: URLからディレクトリ名の抽出などに使う&lt;/li&gt;
&lt;li&gt;置換（replace）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;がある。&lt;/p&gt;
&lt;p&gt;どんなプログラミング言語でもSQLでもBIツールでもこの3種類の処理は備わっている。&lt;/p&gt;
&lt;h3 id="レベル別正規表現"&gt;レベル別正規表現&lt;/h3&gt;
&lt;p&gt;正規表現の学習の詳細は他の教材に任せるが、学ぶ際のコツとして難易度別に段階的に学ぶことが挙げられる。&lt;/p&gt;
&lt;h4 id="レベル1-特殊文字1文字を表すもの"&gt;レベル1: 特殊文字：1文字を表すもの&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.&lt;/code&gt; 何でも1文字（改行以外）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^&lt;/code&gt; 行頭&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$&lt;/code&gt; 行末&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\n&lt;/code&gt; ラインフィード（LF）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\r&lt;/code&gt; キャリッジリターン（CR）&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="レベル1-特定の種類の文字を表すもの"&gt;レベル1: 特定の種類の文字を表すもの&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;\d&lt;/code&gt;: 任意の数字&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\w&lt;/code&gt;: 任意の英数字かアンダースコア&lt;code&gt;_&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\s&lt;/code&gt;: 空白文字（ホワイトスペース、タブ、改行文字）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;\D&lt;/code&gt;などの大文字は否定（数字以外の文字）を表す。&lt;/p&gt;</description></item><item><title>JavaScriptの計測タグと最近のウェブページレンダリング（SPA、SSRなど）</title><link>https://www.marketechlabo.com/web-measurement/measurement-in-spa-ssr-pages/</link><pubDate>Thu, 07 Nov 2024 00:00:00 +0900</pubDate><guid>https://www.marketechlabo.com/web-measurement/measurement-in-spa-ssr-pages/</guid><description>
&lt;h2 id="最近増えているspassrssgとは何か"&gt;最近増えているSPA、SSR、SSGとは何か&lt;/h2&gt;
&lt;p&gt;最近ではSPA（シングルページアプリケーション）、SSR（サーバサイドレンダリング）などといったウェブページの表示の仕組みを採用するサイトが増えている。これらのページではウェブ解析ツールの計測タグや広告のリマーケティングタグなどが正しく動作しないことがある。SPAの仲間にはSSR、SSGがあるが、これらの共通点はSPA内でのページの遷移時に&lt;strong&gt;ページの読み込み処理&lt;/strong&gt;（ロード）が行われない点である。
これらのページではページを最初に表示するときにだけ読み込み処理が行われる。そこでページのアセット（画像やJavaScriptのファイル）がまとめて読み込まれる。その後のページの切り替わり時にはページのボディ部分を部分的に書き換える処理が行われていく。ヘッダの画像などは最初に読み込まれたものがそのまま表示される。jQueryなどの大きなスクリプトファイルをもう一度読み込まれることもなく、最初に読み込んだものが使われ続ける。一方で各ページ固有の写真のファイルなどの新たなアセットだけが追加的に読み込まれることになる。
一方で従来のページはMPA（マルチページアプリケーション）といってこれらと区別することがある。MPAではページが切り替わるたびにページの読み込み処理が行われる。ページが切り替わるたびにページのアセットの取得を行い（画像やスクリプトファイルはキャッシュがあれば毎回ダウンロードしないが）、HTMLのレンダリングもゼロから行う。
SPAでは表示内容を書き換えたいその都度、更新する部分のコンテンツだけをサーバから取得し、レンダリングそのものはブラウザ側で行うものを指すことが多い。
SSRではレンダリングの大部分をサーバで行う、ページの表示内容をサーバ側で組み上げてからブラウザに渡す。ブラウザ側では最小限のレンダリング処理で済ませるものである。それに対してレンダリング処理のすべてをブラウザ側で行うものをクライアントサイドレンダリング（CSR）という。
SSGはクライアント（ブラウザ）側にとってはSSRとあまり変わらないが、サーバ側での処理に違いがある。SSRはブラウザからのリクエストのたびにHTMLを生成するのに対して、SSGはあらかじめHTMLを生成しておく。同じページでもタイミングや人によって表示内容が細かく変わる場合にはSSRでなければならないが、同じページでは表示する内容が同じ、つまり静的サイトの場合にはSSGでいい。ページの表示速度はサーバ側でのHTML生成の時間がない分、SSGのほうが高速になる。
厳密にはSPAでもSSRタイプのものとCSRタイプのものがある、SPAの対になるのがMPAで、SSRの仲間ががSSGで対になるのがCSR、でもSSGはSPAではないのだが、あまり気にする必要はない。計測上はただ一点、&lt;strong&gt;ページの読み込み処理をページ遷移のたびに行うか、行わないか&lt;/strong&gt;を意識すればいい。ページ遷移のたびにページ読み込み処理が行われるのであれば従来通りのトリガー設定でいいが、そうでない場合はトリガーなどの計測設定を変更する必要がある。&lt;/p&gt;
&lt;h2 id="一つのサイトにはmpaや複数の環境のspaが混在する"&gt;一つのサイトにはMPAや複数の環境のSPAが混在する&lt;/h2&gt;
&lt;p&gt;一つのサイトがすべて一つのSPAやSSRだけでできているケースは多いわけではない。**一部の階層のみSSRになっていたり、またSSRであっても異なるシステム（一方がNext.jsで、別の階層がReactなど）**であるケースも多い。タグマネジメントにおいてはそういった複数のレンダリングシステムが混在した環境に対して、サイト全体で計測タグが正しく動作するように設定する必要がある。これは大変難易度が高い。
&lt;figure&gt;
&lt;picture&gt;
&lt;img
loading="lazy"
decoding="async"
alt=""
class="image_figure image_internal image_unprocessed"
src="/images/measurement-spa-pages/rendering_methods_by_directories.png"
/&gt;
&lt;/picture&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="mpaページの基本"&gt;MPAページの基本&lt;/h2&gt;
&lt;p&gt;MPAページでは、GTMタグ読み込み時に発火するページビュートリガーが基本になる。データレイヤーからデータを取得したり、DOMの内容を取得したりする場合にDOM Readyを使うことがある。これについてはこれまでと変わりない。&lt;/p&gt;
&lt;h2 id="spa--ssr--ssgページの基本"&gt;SPA / SSR / SSGページの基本&lt;/h2&gt;
&lt;p&gt;サイト外や当該SPAページ以外から遷移してくるパターンと、SPAの同一ページ内で遷移をするパターンを両方サポートする必要がある。&lt;/p&gt;
&lt;h3 id="初回読み込み時"&gt;初回読み込み時&lt;/h3&gt;
&lt;p&gt;SPAページそのものを読み込むタイミングである。純粋な閲覧開始や、MPAページから遷移してくる、他のシステムのSSRページから遷移してくるケースである。
SPA / SSR / SSGページの初回読み込み時にはGTMのタグも読み込まれるので、ページビュートリガーが適用される。MPAと同様にDOM Readyを使ってもいい。&lt;/p&gt;
&lt;h3 id="次回以降のページ遷移"&gt;次回以降のページ遷移&lt;/h3&gt;
&lt;p&gt;一度SPAページを読み込んだ後の、ページ内での遷移である。ここではページの読み込み処理は行われない。
&lt;strong&gt;簡単なのは「履歴の変更」トリガーを使うこと&lt;/strong&gt;である。「履歴の変更」（&lt;code&gt;gtm.historyChange&lt;/code&gt;）とは、ブラウザでページの読み込みを伴わないURL変更が行われた時に発火するトリガーである。、厳密には&lt;code&gt;window.history.pushState()&lt;/code&gt;または&lt;code&gt;window.history.replaceState()&lt;/code&gt;メソッドが呼び出された時、イベント&lt;code&gt;popstate&lt;/code&gt;が検知された時、URLのハッシュ（フラグメント）部分が書き換えられた時のいずれかに該当した場合になる。
GA4の拡張計測機能では履歴の変更には対応しているが、あくまでGA4のみが対象であって、他のツールのタグや広告タグは対象外なので別途対応が必要となる。そうなると、GA4の拡張計測機能に依存せずにすべてタグマネージャ側で発火制御するほうが管理がしやすくなる。
SPAやSSRでも、最初のページ表示時（読み込み時）は該当しない。そこではページビュートリガーやDOM Readyが該当する。SPAやSSR&lt;strong&gt;内での&lt;/strong&gt;次回以降のページ遷移時に「履歴の変更」トリガーが該当する。つまり従来の「ページビュー」トリガーや「DOM Ready」トリガーなどと、「履歴の変更」トリガーを組み合わせることですべてのページ遷移に対応できるようになる。
しかし「履歴の変更」トリガーの限界がある。履歴の変更トリガーではデータレイヤーやDOMの内容など、ページとのデータ連携は基本的に不可能になる。というのも多くのシステムでは履歴の変更処理後にページ内容の書き換えが非同期で進められるためである。つまり履歴の変更トリガー発生時には古いコンテンツされており、その後でページの表示処理が行われて新しいコンテンツになる。GTMの「履歴の変更」トリガーを使ってページビュー計測をすると、ページタイトルがそのURLと合わないものになるケースがあるのはこれが理由である。&lt;/p&gt;
&lt;h3 id="履歴の変更トリガーの罠"&gt;「履歴の変更」トリガーの罠&lt;/h3&gt;
&lt;p&gt;「履歴の変更」トリガーではSPAやSSR内でのブラウザバックなどの際に想定通りにハンドリングされず、重複してトリガーが適用される（タグが重複発火する）ケースがある。その場合&lt;strong&gt;履歴の変更前後のURLが異なる時にのみ&lt;/strong&gt;履歴の変更トリガーを発火させることで重複発火を回避できる。
「履歴の変更」発生時に変更前のURLはデータレイヤー変数&lt;code&gt;gtm.oldUrl&lt;/code&gt;に、新URLはデータレイヤー変数&lt;code&gt;gtm.newUrl&lt;/code&gt;に格納される。これらをそれぞれGTM変数として設定する。
&lt;figure&gt;
&lt;picture&gt;
&lt;img
loading="lazy"
decoding="async"
alt=""
class="image_figure image_internal image_unprocessed"
src="/images/measurement-spa-pages/spa_variable_oldurl.png"
/&gt;
&lt;/picture&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;picture&gt;
&lt;img
loading="lazy"
decoding="async"
alt=""
class="image_figure image_internal image_unprocessed"
src="/images/measurement-spa-pages/spa_variable_newurl.png"
/&gt;
&lt;/picture&gt;
&lt;/figure&gt;
ここで設定した2個のGTM変数の値が同じかどうかを判定するJavaScript変数を作成する。
&lt;figure&gt;
&lt;picture&gt;
&lt;img
loading="lazy"
decoding="async"
alt=""
class="image_figure image_internal image_unprocessed"
src="/images/measurement-spa-pages/spa_variable_url_condition.png"
/&gt;
&lt;/picture&gt;
&lt;/figure&gt;
この値が&lt;code&gt;true&lt;/code&gt;であれば履歴の変更前後のURLが異なる（発火対象）、&lt;code&gt;false&lt;/code&gt;であれば前後のURLが同じということになる（非発火対象）。
したがって「履歴の変更トリガー」で、この変数が&lt;code&gt;true&lt;/code&gt;になるケースに絞り込んでトリガーを作成する。以下は第1階層が&lt;code&gt;aaa&lt;/code&gt;と&lt;code&gt;bbb&lt;/code&gt;以外の全階層でこの絞り込んだ履歴の変更トリガーを実装する例である。
&lt;figure&gt;
&lt;picture&gt;
&lt;img
loading="lazy"
decoding="async"
alt=""
class="image_figure image_internal image_unprocessed"
src="/images/measurement-spa-pages/spa_trigger_all_page_history_change.png"
/&gt;
&lt;/picture&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id="カスタムイベント"&gt;カスタムイベント&lt;/h3&gt;
&lt;p&gt;履歴の変更トリガーを使う場合はデータ連携はあきらめた方がいい。データ連携が必要な場合はページの切り替え時にアプリケーション（フレームワーク）側の設定でカスタムイベントを発火させ、それをトリガーとして個別のタグを発火させるようにする。
タグマネージャではなく&lt;strong&gt;ウェブサイト側（フレームワークなど）で&lt;/strong&gt;ページ切り替え時の処理に以下の記述を入れる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;dataLayer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;push&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;event&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;custom_page_load&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// （カスタムイベント名は何でもいい）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;category&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;cosmetics&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// （連携するデータ）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここでは&lt;code&gt;custom_page_load&lt;/code&gt;という名前のカスタムイベントとしてページ切り替わりを意味するイベントを作った。GTM側でもこのカスタムイベントに対応したトリガーを作成する。
&lt;figure&gt;
&lt;picture&gt;
&lt;img
loading="lazy"
decoding="async"
alt=""
class="image_figure image_internal image_unprocessed"
src="/images/measurement-spa-pages/spa_trigger_all_page_custom_event.png"
/&gt;
&lt;/picture&gt;
&lt;/figure&gt;
SPA / SSR / SSG内でのページ表示（遷移）時に発生させるイベント名はアプリケーションごとに別々にするのではなく、&lt;strong&gt;サイト全体で統一しておくといい&lt;/strong&gt;。そうすると一つのトリガー設定ですべてのSPAやSSRなどのページに対して共通してページビュー計測できるようになる。
しかしSPAのシステム（フレームワーク）側からカスタムイベントを発生させる場合、技術的な実装上の観点から、前節の「次回以降のページ遷移」だけでなく初回読み込み時にも発生させざるを得ないのが普通である。そこでカスタムイベントを使う場合は、SPAやSSRの階層ではページビューやDOM Readyのトリガー自体を発火させないようにしておく必要がある。つまりページビュートリガー側で除外条件としてSPAのパスを含めておく。以下の例では第1階層が&lt;code&gt;aaa&lt;/code&gt;と&lt;code&gt;bbb&lt;/code&gt;を除外対象としている。
&lt;figure&gt;
&lt;picture&gt;
&lt;img
loading="lazy"
decoding="async"
alt=""
class="image_figure image_internal image_unprocessed"
src="/images/measurement-spa-pages/spa_trigger_all_page_mpa.png"
/&gt;
&lt;/picture&gt;
&lt;/figure&gt;
&lt;/p&gt;</description></item><item><title>JavaScriptでフラグをビットで管理する～複数の状態フラグを少ない容量で管理</title><link>https://www.marketechlabo.com/web-measurement/bit-flags/</link><pubDate>Tue, 21 Feb 2017 00:00:00 +0900</pubDate><guid>https://www.marketechlabo.com/web-measurement/bit-flags/</guid><description>
&lt;p&gt;状態を管理する、その状態に応じて条件分岐するやり方。&lt;/p&gt;
&lt;h2 id="フラグをビットで管理するメリットとケース"&gt;フラグをビットで管理するメリットとケース&lt;/h2&gt;
&lt;p&gt;例: ランディングページで「30秒以上滞在」「スクロール深度50%到達」「フォーム入力開始」を検知し、3つとも満たしたユーザーにのみリターゲティング用のカスタムオーディエンスを送る。あるいは、ECサイトで「トップ閲覧」「カテゴリ閲覧」「詳細閲覧」を1つの数値で持ち、商品詳細まで到達したユーザーにのみ関連商品リコメンドのタグを発火させる。
個別の条件を満たしたときにフラグを立て、その組み合わせを参照して処理を分岐させる。
単純に1フラグを1変数にすると変数の数が増える。
そこで1個の変数で複数の状態をまとめて管理する方法がビットによる管理である。
なおこの考え方はJavaScriptに限らずあらゆるプログラム言語で実装が可能。
管理するフラグが多く、メモリ消費や発生するパケットを小さくする必要があるときに重要となる。&lt;/p&gt;
&lt;h2 id="ビット"&gt;ビット&lt;/h2&gt;
&lt;p&gt;ビットは0または1の2値を表す情報の単位
それを8個つなげたもの、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;11001101&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;は8個の0/1を表す情報を保持している。
&lt;code&gt;11001101&lt;/code&gt;の各桁は0か1しかないので2進数として見ることができる。
これを10進数に置き換えると205ということになる。
8ビットの変数1個（0&lt;del&gt;255の整数）であれば8個のビット（0/1）が収まる。
つまり0&lt;/del&gt;255の整数で8種類の0/1の状態を表せる。
この最小の情報の単位であるビットに対する処理がビット処理である。&lt;/p&gt;
&lt;h2 id="フラグの定義"&gt;フラグの定義&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;DISABLED&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;HOVER&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ACTIVE&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;1&amp;lt;&amp;lt;桁&lt;/code&gt;で、桁は0からスタート&lt;/p&gt;
&lt;h2 id="フラグを設定代入する"&gt;フラグを設定（代入）する&lt;/h2&gt;
&lt;p&gt;まず状態を表す変数を宣言&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="フラグdisabledを立てる"&gt;フラグ&lt;code&gt;DISABLED&lt;/code&gt;を立てる&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DISABLED&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;フラグ&lt;code&gt;DISABLED&lt;/code&gt;と&lt;code&gt;HOVER&lt;/code&gt;を同時に立てる（一度に代入する）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;|=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DISABLED&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;HOVER&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="フラグのセットを作る"&gt;フラグのセットを作る&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DISABLED&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;HOVER&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ACTIVE&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="フラグdisabledを下げる"&gt;フラグ&lt;code&gt;DISABLED&lt;/code&gt;を下げる&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;~&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DISABLED&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;フラグを下げる場合は「&lt;code&gt;&amp;amp;&lt;/code&gt;」にするのと否定の「&lt;code&gt;~&lt;/code&gt;」を付ける
フラグ&lt;code&gt;DISABLED&lt;/code&gt;と&lt;code&gt;HOVER&lt;/code&gt;を同時に下げる（一度に代入する）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;~&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DISABLED&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;HOVER&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="特定のフラグを反転させる"&gt;特定のフラグを反転させる&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;^=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DISABLED&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="特定のフラグを取り出す"&gt;特定のフラグを取り出す&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;state&lt;/code&gt;の中で&lt;code&gt;DISABLED&lt;/code&gt;に対応するビットの値を抜き出す（これが0でなければ&lt;code&gt;DISABLED&lt;/code&gt;のフラグが立っていることになる）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DISABLED&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;state&lt;/code&gt;の中で&lt;code&gt;DISABLED&lt;/code&gt;、&lt;code&gt;HOVER&lt;/code&gt;に対応する部分を抜き出す&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DISABLED&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;HOVER&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;これが0でなければ&lt;code&gt;DISABLED&lt;/code&gt;または&lt;code&gt;HOVER&lt;/code&gt;のフラグが立っていることになる&lt;/li&gt;
&lt;li&gt;これが&lt;code&gt;(STATE.DISABLED | STATE.HOVER)&lt;/code&gt;と等しい場合、&lt;code&gt;DISABLED&lt;/code&gt;と&lt;code&gt;HOVER&lt;/code&gt;の両フラグが立っていることになる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;フラグの取り出しは条件判定で使うことになる。&lt;/p&gt;
&lt;h2 id="逆引き"&gt;逆引き&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;やりたいこと&lt;/th&gt;
&lt;th&gt;演算方法&lt;/th&gt;
&lt;th&gt;演算子&lt;/th&gt;
&lt;th&gt;変更したいビット&lt;/th&gt;
&lt;th&gt;そのままにしたいビット&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ビットをすべて反転させたい&lt;/td&gt;
&lt;td&gt;NOT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;すべて変更される&lt;/td&gt;
&lt;td&gt;指定不可&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;一部のビットを反転させたい&lt;/td&gt;
&lt;td&gt;XOR&lt;/td&gt;
&lt;td&gt;&lt;code&gt;^&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;反転させたいビット: 1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;一部のビットをONにしたい&lt;/td&gt;
&lt;td&gt;OR&lt;/td&gt;
&lt;td&gt;`&lt;/td&gt;
&lt;td&gt;`&lt;/td&gt;
&lt;td&gt;ONにしたいビット: 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;一部のビットをOFFにしたい&lt;/td&gt;
&lt;td&gt;AND&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OFFにしたいビット: 0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="条件判定"&gt;条件判定&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DISABLED&lt;/span&gt;) { &lt;span style="color:#a6e22e"&gt;処理&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DISABLED&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;HOVER&lt;/span&gt;)) { &lt;span style="color:#a6e22e"&gt;処理&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;!!&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STATE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DISABLED&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;処理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ビットを使った条件"&gt;ビットを使った条件&lt;/h2&gt;
&lt;p&gt;UIの状態管理の例。ボタンが無効でなく、かつホバー中の場合にのみクリック処理を実行する。&lt;/p&gt;</description></item></channel></rss>