見出し画像

GTMだけでSHA256ハッシュ化してみた

どこに需要があるか分からない。
でもまとめてみた。
そんな記事です(笑)

運用型広告に携わっていると
「ハッシュ化」という言葉を耳にする機会がありますよね。

Facebook/Instagram広告の『手動詳細マッチング』や『コンバージョンAPI』でもSHA256のハッシュ化が必須です。

今回は「ハッシュ化とは?」「SHA256とは?」という話から
最終的にGTMだけでハッシュ化設定する方法を書いています。

ハッシュ化とは

ハッシュ化とは、元のデータから一定の計算手順に従ってハッシュ値と呼ばれる規則性のない固定長の値を求め、その値によって元のデータを置き換えること。パスワードの保管などでよく用いられる手法である。

引用 - IT用語辞典

簡単にいうと暗号化ですね。
電話番号とかメールアドレスを直接Facebookに送るとセキュリティ的によろしくないため暗号化しましょうね、ということです。(厳密には暗号化は復元できるものですが、ハッシュ化は一方通行なので復元不可)

SHA256って何

SHA-256とは、任意の長さの原文から固定長の特徴的な値を算出するハッシュ関数(要約関数)の一つ。どんな長さの原文からも256ビットのハッシュ値を算出することができる。

引用 - IT用語辞典

「はぁ?」
と思われるかもしれません。

凄い簡単に書くと「ハッシュ化させるための方法の1つ」という認識で概ね間違いないです。

ハッシュ化と運用型広告

運用型広告の中でもFacebookを例にとりましょう。

前述したように、手動詳細マッチングやコンバージョンAPI、あるいはカスタマーリスト作成の際にはユーザーデータのハッシュ化をしてからFacebookへ送信する必要があります。

ピクセルを用いた手動詳細マッチング
サーバーサイドGTM上で動く『Facebook Conversions API Tag』を用いると
Facebook側で自動でハッシュ化して送ってくれます。

※サーバーサイドGTMを活用したFacebookコンバージョンAPIの設定方法についてはこちらを参考ください。

とはいえ、、、
Facebookが自動でハッシュ化してくれるとは言っても、、、
やっぱり不安なので最初からハッシュ化したものを送りたい

そう思うときありますよね?
(ないですかね?)

インハウスの場合は自社でハッシュ化して
そのハッシュ化したものを値として送ればいいので
そこまで困るということはないかもしれません。

代理店の場合もクライアントに依頼すれば良いのですが・・・
「工数を掛けてしまうことになったり
時間がめちゃめちゃ掛かったりするので
なるべく自分達で巻き取って解決したい・・・!」

そう感じたことがある人はこの記事が参考になるかもしれません。

長いですが、ここまで前置きです。
(ちなみに私はプログラマーではないため、専門家からしたらもっと上手い方法があるのかもしれません。。。是非教えて欲しい。)

GTMでハッシュ化への道のり - 起

「カスタムJavaScriptで出来そうじゃね?ハッシュ化させるためのスクリプトとか検索すれば出てくるっしょ!検索検索!」

画像1

まず目につくのは「外部ライブラリ」をダウンロードして用いる方法。
これはGTMでは無理ですね。

なぜならHTMLが置いてあるサーバーと同じサーバーに
そのライブラリを設置しなければいけません。

うん、これは却下。

GTMでハッシュ化への道のり - 承

「カスタムJavaScript」で使えるようにコードを探す。探す。探す。
そうすると『標準ライブラリ』だけで記載してあるコードがいくつか見つかると思います。

ただ、ほぼすべて(というか私が見た限りすべて)非同期処理をしているんですよね。

例えばこんな感じのもの。

<script>
async function sha256(str) {
  // Convert string to ArrayBuffer
  const buff = new Uint8Array([].map.call(str, (c) => c.charCodeAt(0))).buffer;
  // Calculate digest
  const digest = await crypto.subtle.digest('SHA-256', buff);
  // Convert ArrayBuffer to hex string
  // (from: https://stackoverflow.com/a/40031979)
  return [].map.call(new Uint8Array(digest), x => ('00' + x.toString(16)).slice(-2)).join('');
}
</script>

「async function~/await~」という非同期関数を使っています。

GTMでは「async function~/await~」非同期関数は使えません
「カスタムJavaScript」のような変数だけでなく、
「カスタムHTML」といったタグの方でも使えません。

(ついでにアロー関数「=>」も使えません。まぁアロー関数自体は「function~」に書き直せるので大きな問題ではありません。)

ただ、「async function~/await~」非同期関数が『変数』で使えない理由と『タグ』で使えない理由は少し異なります。

タグについてはECMASCRIPTのバージョンが関わっています。
(ECMASCRIPTについて興味ある方は調べてみてください。)

GTMのエンジンはECMASCRIPT5であるため、
それ以降のECMASCRIPT2015とかECMASCRIPT2017の仕様で
記載されたコードは対応範囲外なのです。

なので、ECMASCRIPT5の仕様に変換してあげれば
恐らくGTMのタグでも使える形になると思います。

変数についてはECMASCRIPTの仕様に関わらず
GTMの『変数』で非同期処理が出来ないことから使えません。

まとめると、ECMASCRIPT5の仕様に書き換えた上で、
カスタムHTML(タグ)を利用したら出来るかもしれませんが、
そこまでJavaScriptの知識はないため一旦保留で。。。

う~ん。どうしたものか。

GTMでハッシュ化への道のり - 転

GTMの公式ヘルプなどを漁っているとあるものを発見。
そう、『カスタムテンプレートAPI』です。
https://developers.google.com/tag-manager/templates/api?hl=ja

テンプレートについてまずお話すると、
GTMで新しくタグや変数を作成しようとすると、
『コミュニティ テンプレート ギャラリーで◯◯タイプをさらに見つけましょう』
って出てきます。

画像2

ここをクリックすると
有志の方が作成してくれたテンプレートが色々とあります。

中には凄い便利なものもありますし、
Yahoo!などの公式が出しているものもあります。

画像3

『カスタムテンプレート』に話を戻しましょう。

『カスタムテンプレートAPI』のコアAPIの中に
なんと『sha256』があるじゃないですか。
これは嬉しい。
https://developers.google.com/tag-manager/templates/api?hl=ja#sha256

画像4

つまり『カスタムテンプレート』を自分で作っちゃえばいいじゃん!
という話です。

ちなみに、ギャラリーの中に既存でハッシュ化を実現出来そうなものがないか調べて見ましたがドンピシャで使えるものはなかったです。。

GTMでハッシュ化への道のり - 結

設定する前にもう一度コアAPIのsha256ヘルプを見てみましょう。

入力値の SHA-256 ダイジェストを計算し、ダイジェストが base64 でエンコードされたコールバックを呼び出します(options オブジェクトが別の出力エンコードを指定していない場合)。

こんな記述があります。
base64とかエンコードとか何?と感じるかもしれませんが
すみません、ここは詳細は割愛します。

要するにSHA256でハッシュ化したあと、
出力する方式として色々あるよ~という感じ。

sha256ヘルプによると
デフォルトだと「base64」のようですね。

一方、Facebookが自動でしているsha256ハッシュ化は
「hex」でエンコード
されています。

これは手動詳細マッチングのピクセルに適当に「abc@gmail.com」とか入れてみて、Facebook pixel helperを見れば分かります。

画像5

↓pixel helper↓

画像7

そして、「abc@gmail.com」をsha256でハッシュ化して
base64とhexでエンコードしたものをそれぞれ見てみます。
(例えばこちらのサイトなど参考→https://hogehoge.tk/tool/)

元のテキストは「abc@gmail.com」
☆base64⇒SN25PwswxHVCP+F3gykSxbzc48xyhy+AUWJ5Z+8njgg=
☆hex⇒48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08

というわけで、pixel helperと一致しているのは「hex」の方ですね。

これを踏まえた上でカスタムテンプレートを作っていきましょう!

その前に、ハッシュ化する流れを簡単に書いておきます。

①:カスタムテンプレートAPIを使って『タグ用』のカスタムテンプレートを作成(なぜ『タグ用』かは後述)
②:①のテンプレートを使いタグを作成。このときdataLayerでハッシュ化した値をpushします。
③:dataLayerでpushされた値をGTMで扱うため、データレイヤー変数を作成
④:実際に使うタグ(Facebookのタグなど)を作成。このときトリガーに注意

という感じになります。

つまり実際のハッシュ化の流れは、GTMを使って値をハッシュ化し、それをdataLayerでpushして、pushされた値をまたGTMのデータレイヤー変数で取得

というなんだかマッチポンプのようなことをします。
ただ、タグを経由するしかないのでこうなります。(一発で変数として取得できない)

GTM上での設定手順としては今回は
①→③→②→④で説明していきます。

カスタムテンプレートの作成

まずはGTMから「テンプレート」へ進みます
そうすると上部に「タグテンプレート」、下部に「変数テンプレート」があります。

画像7

今回は「タグテンプレート」を使っていくので
「タグテンプレート」の方で新規をクリック。

「なんで変数じゃなくてタグなの?」

と思うかもしれません。このあたりを少しお話します。

『カスタムテンプレートAPI』のsha256は非同期処理です。
しかし、前述のようにGTMの変数は非同期処理が出来なく、変数は常に同期処理になります。

要するに、GTMは『変数』が非同期処理を遂行するのを「待つ」ことができません。待ってしまうと、変数に依存して値を返すタグとトリガーの動作まで中断されてしまうからですね。

したがって、変数でsha256を使用することはできません。

「sha256」のAPIはタグで使うAPIになります。

※なお、今回はカスタムテンプレート作成における詳しい仕様や「なぜそうなるのか?」の部分は割愛します。

『とりあえず真似して設定してみたら出来る』

という状況をゴールとしたいと思います。※

話を戻しましょう。

「タグテンプレート」で新規を押すと下記のような画面になります。

画像8

「名前」の箇所に適当にネーミングします。今回は「TesstTemplate」

画像9

「項目」タブから「フィールドを追加」をクリック

画像10

「テキスト入力」を選択

画像11

こんな画面になればOK。text1の名称を変更することも出来ますが、デフォルトのままでも問題ないです。

画像12

次にコードに進みます。
コードの詳細を説明しようとすると長くなるので
こういうものだと思って記載してください。

画像13

// テンプレート コードをここに入力します。
const log = require('logToConsole');
const sha256 = require('sha256');
const createQueue = require('createQueue');

sha256(data.text1, (digest) => {
               const dataLayerPush = createQueue('dataLayer');
               dataLayerPush({
                   'sha256_value': digest,
                   'event': 'sha256'
               });
           data.gtmOnSuccess();
       }, data.gtmOnFailure, {outputEncoding: 'hex'});
// タグの終了時に data.gtmOnSuccess を呼び出します。

これで、「text1」に入力した文字列をハッシュ化して、
「sha256_value」というdataLayerの変数名に、ハッシュ化した値を格納してくれます。('sha256_value': 'digest'の部分)

その後、カスタムイベント「sha256」を作成することで
「sha256」というイベント発生時にはdataLayer変数に値が入っている状況になるわけです。('event': 'sha256'の部分)

あとはpushされたdataLayerを変数として使うために
GTMの方でもデータレイヤーの変数を作成します。(後述)

その前にカスタムテンプレートでやることがあります。
「権限」タブから「グローバル変数へのアクセス」をクリック。
「キーを追加」から下記のように設定します。

画像14

ここまで終わったら「保存」
(なお「保存」を押しても自動で前の画面に戻りません。「保存」したあとに、左上の「☓」からページを戻ります)

dataLayerを受け取る変数の作成

カスタムテンプレート内でpushしたdataLayerを受け取る設定をします。
この辺はご存知の方が多いと思うのでサクッといきますが、
変数の新規作成⇒データレイヤーの変数と進み
変数名に先程の「sha256_value」と入力。

ここでは名前は「変数-ハッシュ化」にしています。

画像15

カスタムテンプレートを用いてタグ作成

いよいよ自分で作ったテンプレートを用いてタグを作成します。

タグ>新規>タグの設定 で「カスタム」の箇所を見ると
先程作った「TestTemplate」があるかと思います。

画像16

これをクリックして「text1」とトリガーを設定するだけです。
下記の例では、固定で「あいうえお」という文字列を入れていますが
もちろん変数を入れることも可能です。

例えば、手動詳細マッチング用に取得した変数を
この「text1」に指定することでハッシュ化することが可能。

画像17

画像18

トリガーについては今回はテストなので「All Pages」にしていますが、
必要なところで発火するように適宜変更してもらって大丈夫です。

プレビューを実行してみる

さて、ここまで来たらGTMのプレビューを見てみましょう。

まずイベント。カスタムテンプレート内で作成した「sha256」というイベントが発生しています。

画像19

次に「sha256」のイベント箇所での「Data Layer」を見ます。
すると「sha256_value」に数値が入っています。
実際これは「あいうえお」をハッシュ化してhexでエンコードした文字列になっています。

画像20

では次に「Variables」を見ていきましょう。
「Event」は「sha256」になっており、
先程作成した「変数-ハッシュ化」はdataLayerでpushした値(上記のsha256_valueの値)を取得出来ていますね。

画像21

これで値のハッシュ化に成功です!

実際にタグで使ってみる

GTMでの変数の扱いに慣れている人であれば特に問題ないと思います。
{{}}(二重の中括弧で囲む)ことで変数として使えるようになりますね。

画像25

ポイントはトリガーです。
データレイヤー変数に値が入っているのは「sha256」以降のイベントになります。

例えば、「Container Loaded」や「DOM Ready」では、
まだdataLayerとしてpushされていない可能性もあります。

カスタムテンプレートを作成したときに書いたように
「'sha256_value':'値'」と同時に「'event':'sha256'」をpushしているので
『sha256』のイベント以降であれば取得は出来ています。

そのため「カスタムイベント」のトリガーを作ると良いでしょう。
トリガー>新規>カスタムイベント で、イベント名に「sha256」を入力します。(すべてか一部かは適宜設定ください)

画像23

画像24

タグ全体としてはこうなります。

画像25

この状態で再度プレビューしてみましょう。

sha256で「facebook-ハッシュ化」が発火していると思います。
さらに詳細を見ると下記の様な感じ。

画像26

これだと値がちゃんと取得出来ているか分からないので
右上の「Names / Values」のところを「Values」にしてあげます。
そうすると取得出来ているか確認が可能です。

画像27

なお、この例では「あいうえお」をハッシュ化したものが入っていますが、
Facebookのpixel helperなどと合わせて確認するときは「hogehoge@gmail.com」などのようにメールアドレスの形にしましょう。
メールアドレスの書式になっていないとFacebook側では反応しません

おまけ

「これで1つの値はハッシュ化出来たけど、複数の場合どうするの?」
「実際メールアドレスだけじゃなくて、電話番号とかも同時にハッシュ化したいし・・・」

そんな声が聞こえてきそうですね。

この場合、一番単純なのは
それぞれ用にカスタムテンプレートを作ることですね。

↓この部分↓を変更してあげれば分類できます。

'sha256_value': digest,
'event': 'sha256

例えば
メールアドレス用のカスタムテンプレート

'sha256_email': digest,
'event': 'sha256_email

電話番号用のカスタムテンプレート

'sha256_tel': digest,
'event': 'sha256_tel

みたいな感じにします。

そして『カスタムテンプレートを用いてタグ作成』の章で話したように
メールアドレス用にはメールアドレスの変数を入れて、
電話番号用には電話番号の変数を入れる形です。

ただ、このカスタムプレートを使ったタグのトリガーを「All Pages」にすると
イベント(sha256_emailとsha256_tel)が発生する順序が分からないので
トリガーは工夫して発生イベントの順序を制御する必要があります。

最後に発生するイベントでは全てのdataLayerをpushしているので
全てのデータレイヤー変数に値が入っていることになります。

もしくは、トリガーを「All Pages」にする場合は、
実際にタグで使ってみる』で利用するタグのトリガーを『トリガーグループ』にして「sha256_email」のカスタムイベントと「sha256_tel」のカスタムイベントを選択します。これで「すべてのイベントが発生」したらタグが発火するようにできます。

どちらにせよ・・・

「何個もカスタムテンプレート作るの面倒じゃん・・・」

という場合はカスタムテンプレートの方を少し改造すればOKです。

まず、項目の方で必要な分のテキストを追加します。
メールアドレスの他に2つハッシュ化したい(合計3つハッシュ化したい)のであれば、「text2」「text3」を追加します。

画像28

そして、コードの方も書き換えます。
例えばオブジェクトとしてdataLayerにpushしたければこんな感じ

// テンプレート コードをここに入力します。
const log = require('logToConsole');
const sha256 = require('sha256');
const createQueue = require('createQueue');

//success/failure const

const onSuccess = () =>{
 data.gtmOnSuccess();
};
const onFailure = () => {
 data.gtmOnFailure();
};
sha256(data.text1, (digest1) => {
 sha256(data.text2, (digest2) => {
   sha256(data.text3, (digest3) => {
     
     const hashes = {'email':digest1, 'phone':digest2, 'name':digest3};
     const dataLayerPush = createQueue('dataLayer');
               dataLayerPush({
                   'sha256_object': hashes,
                   'event': 'sha265_object'
               });
     onSuccess();
   }, onFailure,{outputEncoding: 'hex'});
  onSuccess();
   }, onFailure,{outputEncoding: 'hex'});
onSuccess();
   }, onFailure,{outputEncoding: 'hex'});      
// タグの終了時に data.gtmOnSuccess を呼び出します。

データレイヤーの変数で「sha256_object.email」とか書けばそれぞれの値を扱えるようになります。「sha256_object」にするともちろんオブジェクトとして取得されます。

一方、配列にしたいなら

// テンプレート コードをここに入力します。
const log = require('logToConsole');
const sha256 = require('sha256');
const createQueue = require('createQueue');

//success/failure const

const onSuccess = () =>{
 data.gtmOnSuccess();
};
const onFailure = () => {
 data.gtmOnFailure();
};
sha256(data.text1, (digest1) => {
 sha256(data.text2, (digest2) => {
   sha256(data.text3, (digest3) => {
     
     const hashes = [digest1, digest2, digest3];
     const dataLayerPush = createQueue('dataLayer');
               dataLayerPush({
                   'sha256_array': hashes,
                   'event': 'sha256_array'
               });
     onSuccess();
   }, onFailure,{outputEncoding: 'hex'});
  onSuccess();
   }, onFailure,{outputEncoding: 'hex'});
onSuccess();
   }, onFailure,{outputEncoding: 'hex'});      
// タグの終了時に data.gtmOnSuccess を呼び出します。

のような感じ。ほぼオブジェクトと同じですね。

[digest1, digest2, digest3]をdataLayerでpushしているわけですが、
この場合データレイヤーの変数で「sha256_array.0」「sha256_array.1」「sha256_array.2」とかすればそれぞれの値を取得出来ます。

こちらももちろん「sha256_array」であれば配列を取得します。

というわけで、1つのイベントに対して複数の値をハッシュ化して取得出来るので、それぞれで設定するよりはトリガーもごちゃごちゃしなくて簡単かと思います。

(ただオブジェクトとか配列のコードの書き方はもっと上手い方法ある気がする)

今回は以上です。

Bye Bye.

追記(2021年7月2日)

「GTMでハッシュ化への道のり - 起」で書いた内容に追記。

執筆時は、外部ライブラリをダウンロードしてディレクトリ内に設置する方法しか見つからなかったのですが、
jQueryのようにライブラリをロードして使用する方法がありました。

js-sha256ライブラリ:https://github.com/emn178/js-sha256
CDNのロード用URL:https://cdnjs.cloudflare.com/ajax/libs/js-sha256/0.9.0/sha256.min.js

これを使えばもう少し簡単に設定出来そうですね。

広告運用に関して詳しくお話を聞きたいという企業様がいらっしゃいましたら、こちらからお問い合わせをお願い致します。

私たちの会社で働く事に少しでも興味を持っていただけたら、ぜひ応募フォームよりご連絡ください。


この記事が気に入ったらサポートをしてみませんか?