<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>GTM on Marketechlabo</title><link>https://www.marketechlabo.com/tags/gtm/</link><description>Recent content in GTM 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/gtm/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>Googleタグマネージャーの使い方＆設定をExcelで出力するツール</title><link>https://www.marketechlabo.com/web-measurement/tag-management-gtm-2/</link><pubDate>Tue, 17 Sep 2019 00:00:00 +0900</pubDate><guid>https://www.marketechlabo.com/web-measurement/tag-management-gtm-2/</guid><description>
&lt;p&gt;Googleタグマネージャー（GTM）を使ったタグマネジメントについて解説する。前半ではタグマネジメントの概念と仕組みの一般論、後半ではGTMの具体的な設定方法を説明する。&lt;/p&gt;
&lt;h2 id="タグマネジメントとタグマネージャ"&gt;タグマネジメントとタグマネージャ&lt;/h2&gt;
&lt;p&gt;タグマネジメントとはwebサイトに設置するタグの一元管理である。管理すべきタグには以下のようなものがある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;アクセス解析ツールのタグ&lt;/li&gt;
&lt;li&gt;広告のコンバージョンタグ&lt;/li&gt;
&lt;li&gt;リマーケティングタグ&lt;/li&gt;
&lt;li&gt;接客ツール（チャットなど）のタグ&lt;/li&gt;
&lt;li&gt;ABテストツールのタグ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;web施策が進んでいくと、これらのタグを複数、それぞれ異なるページに設置する必要が出てくる。どのタグをどんな条件で設置したか管理し、不要になったタグは削除するなどの運用を徹底しておかないと、同じ目的のタグを重複設置したり、古いタグがページ表示の不具合を引き起こしたりする。担当者が変わった際にも「どこにどのタグをどんな目的で設置したか」を把握できるようにしておく必要がある。&lt;/p&gt;
&lt;p&gt;タグマネージャはこの管理を支援するツールで、サイトのHTMLにはタグマネージャのタグのみを設置し、個別のタグは管理画面上で設定する。ただしツール導入だけで管理が完結するわけではなく、人の手による運用ルールもセットで成立する。タグと発火条件（※タグが実行されることを「発火する」（fire）という）、名前と目的を一覧管理する管理表を作るといい。&lt;/p&gt;
&lt;p&gt;タグマネージャを導入するメリット&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;タグの追加・削除時にHTMLの改修が不要→設置工数が大幅低減&lt;/li&gt;
&lt;li&gt;検証モードで本番公開前に動作確認できる&lt;/li&gt;
&lt;li&gt;タグの実行順序を指定できる&lt;/li&gt;
&lt;li&gt;不具合発生時に過去の状態にロールバックできる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;どのタグマネージャも共通して設定するのがタグ、発火条件（トリガー）、データレイヤー（タグマネージャにデータを渡す仕組み）の3点である。&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;picture&gt;
&lt;img
loading="lazy"
decoding="async"
alt="タグマネージャの仕組み"
class="image_figure image_internal image_unprocessed"
src="/images/gtm/tagmanager.png"
/&gt;
&lt;/picture&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="gtmとは"&gt;GTMとは&lt;/h2&gt;
&lt;p&gt;Googleタグマネージャー（GTM）はGoogleが提供している無料のタグマネージャ。Googleアナリティクス（GA4）やGoogle広告との親和性が高く、無料でもあるので独立したタグマネージャとしても十分使える。&lt;/p&gt;
&lt;h2 id="設置"&gt;設置&lt;/h2&gt;
&lt;p&gt;タグは2個あり、両方設置する。それぞれ設置個所が決まっている。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;head&amp;gt;～&amp;lt;/head&amp;gt;&lt;/code&gt;内&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;開始タグの直後&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ここにないとSearch Consoleなどの認証で失敗する。&lt;/p&gt;
&lt;h2 id="タグの設定"&gt;タグの設定&lt;/h2&gt;
&lt;p&gt;&lt;figure&gt;
&lt;picture&gt;
&lt;img
loading="lazy"
decoding="async"
alt="コンテナ"
class="image_figure image_internal image_unprocessed"
src="/images/gtm/container.png"
/&gt;
&lt;/picture&gt;
&lt;/figure&gt;
タグ＋トリガー＋変数のセット→これら設定の一式をコンテナという。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;タグ→実行するタグ&lt;/li&gt;
&lt;li&gt;トリガー→タグの実行（発火）条件&lt;/li&gt;
&lt;li&gt;変数
&lt;ul&gt;
&lt;li&gt;トリガーの中での条件判定に使う&lt;/li&gt;
&lt;li&gt;タグに動的に値を渡す（データレイヤー）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;条件判定で使う変数は、たとえばクリックしたリンクのURLやログイン済みかどうかのフラグなど、その値によってタグを実行するかどうかの扱いが変わるもの。
タグに動的に値を渡すというのはサーバから出力される問合せ番号や注文番号など。サーバで処理をした結果をGoogleアナリティクスや広告のコンバージョンタグなどに送りたい場合に使う。&lt;/p&gt;
&lt;h2 id="コンテナ"&gt;コンテナ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;現在のタグ一式（タグ＋トリガー＋変数）をまとめたもの&lt;/li&gt;
&lt;li&gt;タグを登録しただけでは有効にならず、公開（パブリッシュ）するとはじめて本番環境に反映される&lt;/li&gt;
&lt;li&gt;バージョン管理の仕組みがあり、過去のバージョンへのロールバックも容易&lt;/li&gt;
&lt;li&gt;複数人で更新可能（ワークスペース）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ワークスペース"&gt;ワークスペース&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;複数人で同時に一つのコンテナを管理、更新できる&lt;/li&gt;
&lt;li&gt;その際の各人の作業用のコンテナをワークスペースという&lt;/li&gt;
&lt;li&gt;自分のワークスペースで行った設定をコンテナに反映し、公開する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ワークスペースと現在のコンテナとの差分を管理する。
コンテナは複数人で更新するため、現在のコンテナは必ずしも自分がワークスペースを作成した時点のバージョンと一致するわけではない（自分がコンテナを取得した以降に他人がコンテナを更新している可能性がある）。他人がコンテナへのマージをした後、自分の変更点のみマージすることが可能。
&lt;figure&gt;
&lt;picture&gt;
&lt;img
loading="lazy"
decoding="async"
alt="ワークスペース"
class="image_figure image_internal image_unprocessed"
src="/images/gtm/workspace.jpg"
/&gt;
&lt;/picture&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id="公開"&gt;公開&lt;/h3&gt;
&lt;p&gt;&lt;figure&gt;
&lt;picture&gt;
&lt;img
loading="lazy"
decoding="async"
alt="送信"
class="image_figure image_internal image_unprocessed"
src="/images/gtm/push.jpg"
/&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/gtm/publish.jpg"
/&gt;
&lt;/picture&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id="設定の流れ"&gt;設定の流れ&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;現在公開されている（最新の）コンテナからコピーしてワークスペースを作る&lt;/li&gt;
&lt;li&gt;自分のワークスペースで設定&lt;/li&gt;
&lt;li&gt;動作確認（プレビュー）&lt;/li&gt;
&lt;li&gt;「送信」して変更を最新のバージョンのコンテナと比較、確認&lt;/li&gt;
&lt;li&gt;「公開」&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;送信→公開するのを忘れずに。初心者あるある。&lt;/p&gt;</description></item><item><title>高度な計測に使えるGTMの黒魔術とタグアシスタントの裏技</title><link>https://www.marketechlabo.com/web-measurement/google-analytics-gtm-advanced-settings/</link><pubDate>Thu, 13 Aug 2020 00:00:00 +0900</pubDate><guid>https://www.marketechlabo.com/web-measurement/google-analytics-gtm-advanced-settings/</guid><description>
&lt;p&gt;GTMとGA4の高度な使い方。設定しておくと便利な変数やトリガーの使い方に加え、データレイヤーを徹底的に使いこなす。さらには計測だけでなく検証の手間を大幅に省くタグアシスタントの裏技を紹介する。&lt;/p&gt;
&lt;h2 id="gtm設定の黒魔術"&gt;GTM設定の黒魔術&lt;/h2&gt;
&lt;h3 id="便利な変数"&gt;便利な変数&lt;/h3&gt;
&lt;h4 id="ページビューid"&gt;ページビューID&lt;/h4&gt;
&lt;p&gt;ページビュー固有のID。
一度ページを読み込んでから、次に読み込むまでの間で保持されるIDで、そのIDをさまざまなツールに送ればそれをキーにデータ連携できる。
ツールA,B,Cの間でIDを連携する場合、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ツールAのIDを取得→Bに送る&lt;/li&gt;
&lt;li&gt;ツールAのIDを取得→Cに送る&lt;/li&gt;
&lt;li&gt;ツールBのIDを取得→Cに送る&lt;/li&gt;
&lt;li&gt;（CのIDを取得→Aに送る？）&lt;/li&gt;
&lt;li&gt;（CのIDを取得→Bに送る？）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;など、ツール数が増えると複雑になる。
ツールAのIDはツールAのタグが処理完了しないと取得できず、それを受けてIDを送るタグはその後に発火させる必要があるなど、タイミングのコントロールも難しくなる。
ページビューIDを使うと&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PVID→ツールAに送る&lt;/li&gt;
&lt;li&gt;PVID→ツールBに送る&lt;/li&gt;
&lt;li&gt;PVID→ツールCに送る&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;となるのでシンプル。ページビューIDは最初に生成しておけばいい。
ログ分析を進めていくと、どのイベントがどのページビューにおいて発生したものなのか知りたくなることがある。たとえばスクロールや動画再生などは典型的。イベントのレコードでページパスは記録されている（どこのページかはわかる）が、いつのページビューかは実はわからない。
またページの表示内容を変えるABテストもどのページビューにおいて発生したのかがわからないと分析が不正確になる（同じトップページでも1PV目なのか2PV目なのか）。
これらは単純にログを上から見ていけばわかるというものではない。たとえば最初にタブをまとめて開いておいて、後でページ閲覧するケース。この場合ページビューヒットとイベントヒットの順番がわからなくなる。
これを解決するためにページビューに対してIDを割り振るといい。同一ページビューに対するすべてのヒット（ページビュー、イベント、トランザクション）はすべて同じIDが割り振られる。つまりページビューに紐づけることができるようになる。&lt;/p&gt;
&lt;p&gt;GA4ではユーザ（&lt;code&gt;user_pseudo_id&lt;/code&gt;）とセッション（&lt;code&gt;ga_session_id&lt;/code&gt;）に対してIDが割り振られていることは知られているが、実は&lt;code&gt;batch_page_id&lt;/code&gt;がハードナビゲーションのページではページビューIDに該当する。しかしこの値はGA4以外のツールに連携することができないため、他のツールを含めて同じページビューIDの値を格納するためには、GTMで変数として設定する必要がある。&lt;/p&gt;
&lt;p&gt;以下を変数／カスタムJavaScriptに設定する&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;function&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:#f92672"&gt;!&lt;/span&gt;window.&lt;span style="color:#a6e22e"&gt;_pv_id&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; window.&lt;span style="color:#a6e22e"&gt;_pv_id&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;crypto&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;randomUUID&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;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; window.&lt;span style="color:#a6e22e"&gt;_pv_id&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;最初に一度限りページビューIDを生成してwindowオブジェクトに保存する。
2回目以降はwindowオブジェクトの中のページビューIDを参照する。
&lt;code&gt;crypto.randomUUID()&lt;/code&gt;はUUID v4形式の一意なIDを生成する標準APIで、すべてのモダンブラウザで利用できる。
この変数を各ツールでカスタム変数（GA4ではイベントパラメータ）としてセットする。&lt;/p&gt;
&lt;h4 id="データレイヤーイベントのおすすめ設定"&gt;データレイヤーイベントのおすすめ設定&lt;/h4&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:#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;イベント名&amp;#39;&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;time&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; Math.&lt;span style="color:#a6e22e"&gt;round&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;performance&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;now&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;performance.now()&lt;/code&gt;はナビゲーション開始からの経過ミリ秒を返す標準APIで、高精度かつDeprecatedでない。&lt;/p&gt;
&lt;h3 id="便利なトリガー"&gt;便利なトリガー&lt;/h3&gt;
&lt;h4 id="もしもイベントが発生していなかったらという条件トリガー"&gt;「もしもイベントが発生していなかったら」という条件（トリガー）&lt;/h4&gt;
&lt;p&gt;トリガーで「イベントが発生したら・・・」という条件は設定できる。
そして「あるイベントAが発生した時、イベントBが発生していたら・・・」はトリガーグループの機能を使えばいい。
では「イベントAが発生したとき、イベントBが発生していなかったら・・・」という条件はどうやって実現するのか？
そこでデータレイヤーイベントを使う。&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;filter&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;) { &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;event&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;イベント名&amp;#39;&lt;/span&gt; }).&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これが&lt;code&gt;true&lt;/code&gt;であればそのイベントは発生していない。
イベントBが発生していなければイベントCを発生させるコードが以下になる。
これをトリガーAによって呼び出されるカスタムHTMLタグとして設定し、トリガーにデータレイヤーイベント「イベントC」を設定すればいい。&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;filter&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;) { &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;event&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;イベントB&amp;#39;&lt;/span&gt; }).&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&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 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;イベントC&amp;#39;&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;h4 id="abテストウェブ接客ツール"&gt;ABテスト／ウェブ接客ツール&lt;/h4&gt;
&lt;p&gt;KARTEなどのABテストツール／ウェブ接客ツール（ウェブの出し分けツール）を計測ツールと連携する場合、ABテストで表示するHTML内に以下のスクリプトを入れておく&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>