Categories
アナリティクス

Googleタグマネージャーを使う場合のコンテンツセキュリティポリシーの設定

Googleタグマネージャーは今では一般的なツールとなっていますが、 ブラウザなどによるセキュリティ関連の新しい仕様によって、あるときから急にタグマネージャーが使えないといったことが起きたりします。

コンテンツセキュリティポリシー(CSP)とは

そのうちの1つでよくあるのがコンテンツセキュリティポリシー(Content Security Policy:CSP)です。ざっくり説明すると、 Webサイト・ページはクロスサイトスクリプティング(XSS)などに対する脆弱性があるのですが、ファイルやスクリプトなどのリソースを拒否・受け入れする仕様です。

つまり、ページで「特定のサイトからのスクリプト(ファイル)しか使わないので、ほかはすべて拒否します」といった宣言をし、ブラウザはそれをもとにスクリプトの取捨選択をするといった感じです。

GoogleタグマネージャーやGoogleアナリティクスも例外ではなく、ここで宣言をしておかないと使えなくなり、Chromeなどのブラウザのコンソールには下記のようなエラーが表示されます。

コンテンツセキュリティポリシーの設定と種類

コンテンツセキュリティポリシーの設定

CSPの設定方法は主に HTTPレスポンスヘッダと<meta>タグの2種類あります。(他にもありますが割愛します)

  • HTTPヘッダー:Content-Security-Policy: default-src ‘self’
  • metaタグ:<meta http-equiv=”Content-Security-Policy” content=”default-src ‘self'”>

上記の default-src ‘self’ の部分をディレクティブと呼び、複数のディレクティブを設定する場合は;でつなげます。

ちなみに、上記の設定は「すべてのコンテンツを自身のドメイン(サブドメインは除く)から取得する」ということを表しています。

コンテンツセキュリティポリシーの制御対象

CSPでは制御対象のリソースを指定できます。主なものは以下になります。

  • script-src:Javascriptの読み込み
  • style-src:CSSの読み込み
  • frame-src:<iframe>による読み込み
  • default-src :設定がない場合に適用

Googleタグマネージャーへの影響

このようにCSPでリソースの取得の制限をしているので、このWebサイトから見たら外部に当たるGoogleタグマネージャーやGoogleアナリティクスも対象になってしまいます。

下記の例では、すべてのコンテンツを自身のドメイン (サブドメインを除く)からのみ許可しているため、 GoogleタグマネージャーやGoogleアナリティクスのスニペット(スクリプト)は無効になります。

<meta http-equiv="Content-Security-Policy" content="default-src 'self'">

Googleタグマネージャーが使えるようにするためのCSPの設定

基本設定

Googleタグマネージャーを使えるようにするには、まず最初にCSPのscript-src に ‘unsafe-inline’ を追加します。

script-src: 'unsafe-inline' https://www.googletagmanager.com
img-src: https://www.googletagmanager.com

非セキュアな場合はimg-srcディレクティブのGoogleタグマネージャーをhttpにします。

script-src: 'unsafe-inline' https://www.googletagmanager.com
img-src: http://www.googletagmanager.com

カスタム JavaScript変数

カスタムJavaScript変数を使用している場合はscript-src: ‘unsafe-eval’も追加する必要があります。

script-src: 'unsafe-eval'

プレビュー モード

Googleタグマネージャーのプレビューモードを使う場合は、さらにCSPに下記のディレクティブを追加します。

script-src: https://tagmanager.google.com
style-src: https://tagmanager.google.com https://fonts.googleapis.com
img-src: https://ssl.gstatic.com https://www.gstatic.com
font-src: https://fonts.gstatic.com data:

非セキュアな場合はscript-src: https://tagmanager.google.comのプロトコルをhttpに変更してください。

Googleアナリティクスを使えるようにするためのCSPの設定

Googleアナリティクスを使用する場合はgoogle-analytics.comもCSPの設定に加えなければなりません。

script-src: https://www.google-analytics.com https://ssl.google-analytics.com
img-src: https://www.google-analytics.com
connect-src: https://www.google-analytics.com

非セキュアな場合はscript-src ディレクティブで https://ssl.google-analytics.comを削除して構いません。

Web開発者との情報共有が大切

Gerd AltmannによるPixabayからの画像

このCSPの設定は通常はWeb開発者が行っていますが、彼らはタグマネージャーやアナリティクスについてはあまり気にしていません。そのため、CSPの設定を追加しても連絡が来ないことはよくあります。

その一方で、Web分析者やタグマネージャーの設定者もCSPなんてふだんは気にしないですし、内容もわかりません。コンソールにエラーが出ても通常は無視するでしょう。

アナリティクスにイベントやページビューが出てこないことはすぐに気づきますが、その原因を探すのは難しいです。

ですので、問題を防ぐにはふだんからWeb開発者との情報共有が大切です。コミュニケーションを取っておくことで、Web開発者から「今度CSPの設定を入れることになりました。CSPとは・・・・」といったことを教えてもらうことで、「タグマネージャーやアナリティクスに影響がでるかもしれない」と気づくことができます。

]]>
Categories
Webマーケティング アナリティクス

要素の中身やデータが変更された時はMutationObserver

onChangeはformでしか使えない 「トップのメイン画像がスライドして表示されたときに拡張eコマースの商品のインプレッションを計測するように」と言われたとき、どうしますか? 「画像がスライドされるならGoogle Tag Managerの『要素の表示』トリガーが使えるのでは?」と思ったのですが、この画像たちはすでに表示されているようになっていて使えないという事実が判明。 画像の横の位置が動的に変わる事でスライドされるように表示されていたので、「javascriptのonChange関数やjQueryのchange関数を使えばできるなぁ」と思ったのですが、onChange関数はselectなどのformでしか使えないという事なのでこれまた却下。 (参考:HTML onchange Event Attribute(w3schools.com)

要素の属性値などを監視するMutationObserver

今回、この画像を含むdivではいくつかの要素の属性値が変わっていました。そこで今回は、MutationObserverクラスを使います。

MutationObserverクラスで指定の要素を監視

// 1.監視する対象のIDを指定
var targetNode = document.getElementById('XXXXX');
// 2.MutationObserverのオプションを実行前に指定
var config = { attributes: true, , attributeFilter: ['class','属性名'], childList: true, subtree: true };
// 3. 変更があった時に実行したい処理をここに記述
var callback = function(mutationsList, observer) {
    for(var mutation of mutationsList) {
         if (mutation.type == 'attributes') {
            // 属性が変わった時に実行したい場合はここに書く
            console.log(mutation.attributeName + ' が変わりました');
        }else if (mutation.type == 'characterData') {
            // データが変わった時に実行したい場合はここに書く
        }else if (mutation.type == 'childList') {
            // 対象ノードの子ノード(テキストノードも含む)が変わった時に実行したい場合はここに書く
        }
    }
};
// 4. MutationObserverインスタンスの作成
var observer = new MutationObserver(callback);
// 5. 対象ノードの監視開始
observer.observe(targetNode, config);
// 6. 監視を終了するときにはdisconnect()を実行
// observer.disconnect();

MutationObserverオプションはできるだけ設定すべき

2のMutationObserverのオプションのうち、attribute、characterData、childListは必ず設定しておくことをお勧めします。特にchildListをfalseにしないと、子ノードに変更があった場合にもイベントが発生するため、注意しましょう。

MutationObserverのオプション一覧

childList対象ノードの子ノード(テキストノードも含む)に対する追加・削除を監視する場合は true にします。
attributes対象ノードの属性に対する変更を監視する場合は true にします。
characterData対象ノードのデータに対する変更を監視する場合は true にします。
subtree対象ノードとその子孫ノードに対する変更を監視する場合は true にします。
attributeOldValue対象ノードの変更前の属性値を記録する場合は true にします(attributes が true の時に有効)。
characterDataOldValue対象ノードの変更前のデータを記録する場合は true にします(characterData が true の時に有効)。
attributeFilterすべての属性の変更を監視する必要がない場合は、(名前空間を除いた)属性ローカル名の配列を指定します。
3のif句内で実行したいことを記述します。今回は分けていますが、属性の変更時のみだけで良い場合は、最初のif部分だけで構いません。上にも書いていますが、子ノードの変更を監視したくない場合はわざと if (mutation.type == ‘childList’) 句を用意して中身を空欄にしておくなどしておいた方が安全です。 4と5はお決まりの書き方なので、そのまま使ってください。 6については終了させたいときに呼び出してください。]]>

Categories
Webマーケティング アナリティクス

複数のトリガーをすべて満たしたら発生させるトリガーグループ

複数のトリガーを条件に使える新機能「トリガーグループ」 Googleタグマネージャーを使っていると、ある条件を満たした後に、異なる別の条件を満たした場合にのみイベントを発生させたい、ということはありませんでしたか?たとえば、ページ内にあるいいねボタンをクリックした場合ではく、ページ内の動画を1分以上見た後に、いいねボタンを押した場合にイベント発生させたい、といったケースです。 Google Tag Managerが2019年3月下旬に突然、「トリガーグループ」という新たなトリガーをリリースしました。

トリガーグループの用途

トリガーグループの主な使い道は複数のトリガーを同一ページ内で発生した場合に発生させる時に有効です。 主に、
  • ページスクロール
  • 閲覧時間
  • ページ内のボタンクリック(遷移しない)
  • 動画閲覧
といった場合の組み合わせになるでしょう。

トリガーグループの作り方

トリガーグループの作り方はとても簡単です。
  1. 新規トリガーの作成
  2. トリガーグループを選択
  3. 必要なトリガーを選択

  4. 発生させる条件を設定(必要であれば)

注意点

とても簡単に作れるトリガーグループですが、いくつか注意点があります。

ページ遷移をしたときは発火しない

ページ遷移をしてしまうとトリガーが初期化されてしまうので、使えません。

発火の順番は指定できない

上記の例で言うと、フッターまでスクロールするのが先の場合でも、レビューを表示させるのが先の場合でもどちらでもこのトリガーグループは発火してしまいます。 順番を指定したい場合は、変数を用意して、各トリガーが発火するタイミングで変数に値(例:トリガー名)を挿入し、後のトリガーが発火した際に、最新の変数の値が2つ目のトリガーの値になっているか?という条件を入れると良いでしょう。

トリガーの発生タイミングは最後のトリガーの発火タイミングではない

これは少々ややこしいのですが、トリガーグループで指定されているトリガーのうち、最後のトリガーが発火された後にgtm.triggerGroupというトリガーが発火されます。このタイミングではじめてタグが実行されます。

1つのトリガーグループは1度しか発生しない

gtm.triggerGroupが1度しか発火しないため、各トリガーの発生回数を制限していなくてもこのトリガーグループは1回しか発火されません。 ]]>