JavaScript
GoogleAnalytics
GoogleTagManager

dataLayer内のデータを自在に取得するJavaScriptコード

JSON配列、即ちGTM(Google Tag Maneger)で使用するdataLayerから自在に値を取り出すためのサンプルコード集。

本記事ではGoogle Anaylticsの拡張eコマーストラッキングのデモサイトの購入完了ページからdataLayerとして出力された以下のJSON配列を動作確認に使用している。

sampleDataLayer
[{"event":"checkout","ecommerce":{"checkout":{"actionField":{"step":5,"action":"checkout"},"products":[{"id":"9bdd2","name":"Compton T-Shirt","price":"44.00","brand":"Compton","category":"T-Shirts","variant":"red","dimension1":"M","position":0,"quantity":1},{"id":"bc823","name":"Fuelworks T-Shirt","price":"92.00","brand":"Fuelworks","category":"T-Shirts","variant":"red","dimension1":"M","position":1,"quantity":1},{"id":"6c3b0","name":"Zappix T-Shirt","price":"99.00","brand":"Zappix","category":"T-Shirts","variant":"red","dimension1":"M","position":2,"quantity":1}]},"promoView":{"promotions":[{"id":"bts","name":"Back To School","creative":"CHECKOUT right","position":"right sidebar"}]},"checkout_option":{"actionField":{"step":3,"option":"Visa","action":"checkout_option"}},"purchase":{"actionField":{"id":"50c165a2-34be-45aa-93bb-8f967682e27d","affiliation":"Online Store","revenue":245,"tax":"5.00","shipping":"5.00","action":"purchase"},"products":[{"id":"9bdd2","name":"Compton T-Shirt","price":"44.00","brand":"Compton","category":"T-Shirts","variant":"red","dimension1":"M","position":0,"quantity":1},{"id":"bc823","name":"Fuelworks T-Shirt","price":"92.00","brand":"Fuelworks","category":"T-Shirts","variant":"red","dimension1":"M","position":1,"quantity":1},{"id":"6c3b0","name":"Zappix T-Shirt","price":"99.00","brand":"Zappix","category":"T-Shirts","variant":"red","dimension1":"M","position":2,"quantity":1}]}},"gtm.uniqueEventId":0},{"gtm.start":1504889450609,"event":"gtm.js","gtm.uniqueEventId":2},{"event":"gtm.dom","gtm.uniqueEventId":3},{"event":"gtm.load","gtm.uniqueEventId":5},{"event":"checkout","ecommerce":{"checkout":{"actionField":{"step":4,"action":"checkout"},"products":[{"id":"9bdd2","name":"Compton T-Shirt","price":"44.00","brand":"Compton","category":"T-Shirts","variant":"red","dimension1":"M","position":0,"quantity":1},{"id":"bc823","name":"Fuelworks T-Shirt","price":"92.00","brand":"Fuelworks","category":"T-Shirts","variant":"red","dimension1":"M","position":1,"quantity":1},{"id":"6c3b0","name":"Zappix T-Shirt","price":"99.00","brand":"Zappix","category":"T-Shirts","variant":"red","dimension1":"M","position":2,"quantity":1}]},"promoView":{"promotions":[{"id":"bts","name":"Back To School","creative":"CHECKOUT right","position":"right sidebar"}]}},"gtm.uniqueEventId":6},{"event":"checkout","ecommerce":{"checkout":{"actionField":{"step":5,"action":"checkout"},"products":[{"id":"9bdd2","name":"Compton T-Shirt","price":"44.00","brand":"Compton","category":"T-Shirts","variant":"red","dimension1":"M","position":0,"quantity":1},{"id":"bc823","name":"Fuelworks T-Shirt","price":"92.00","brand":"Fuelworks","category":"T-Shirts","variant":"red","dimension1":"M","position":1,"quantity":1},{"id":"6c3b0","name":"Zappix T-Shirt","price":"99.00","brand":"Zappix","category":"T-Shirts","variant":"red","dimension1":"M","position":2,"quantity":1}]},"promoView":{"promotions":[{"id":"bts","name":"Back To School","creative":"CHECKOUT right","position":"right sidebar"}]}},"gtm.uniqueEventId":8},{"event":"checkoutOption","ecommerce":{"checkout_option":{"actionField":{"step":3,"option":"Visa","action":"checkout_option"}}},"gtm.uniqueEventId":10},{"event":"checkout","ecommerce":{"checkout":{"actionField":{"step":5,"action":"checkout"},"products":[{"id":"9bdd2","name":"Compton T-Shirt","price":"44.00","brand":"Compton","category":"T-Shirts","variant":"red","dimension1":"M","position":0,"quantity":1},{"id":"bc823","name":"Fuelworks T-Shirt","price":"92.00","brand":"Fuelworks","category":"T-Shirts","variant":"red","dimension1":"M","position":1,"quantity":1},{"id":"6c3b0","name":"Zappix T-Shirt","price":"99.00","brand":"Zappix","category":"T-Shirts","variant":"red","dimension1":"M","position":2,"quantity":1}]},"promoView":{"promotions":[{"id":"bts","name":"Back To School","creative":"CHECKOUT right","position":"right sidebar"}]}},"gtm.uniqueEventId":12},{"event":"checkout","ecommerce":{"checkout":{"actionField":{"step":5,"action":"checkout"},"products":[{"id":"9bdd2","name":"Compton T-Shirt","price":"44.00","brand":"Compton","category":"T-Shirts","variant":"red","dimension1":"M","position":0,"quantity":1},{"id":"bc823","name":"Fuelworks T-Shirt","price":"92.00","brand":"Fuelworks","category":"T-Shirts","variant":"red","dimension1":"M","position":1,"quantity":1},{"id":"6c3b0","name":"Zappix T-Shirt","price":"99.00","brand":"Zappix","category":"T-Shirts","variant":"red","dimension1":"M","position":2,"quantity":1}]},"promoView":{"promotions":[{"id":"bts","name":"Back To School","creative":"CHECKOUT right","position":"right sidebar"}]}},"gtm.uniqueEventId":14},{"event":"transaction","ecommerce":{"purchase":{"actionField":{"id":"50c165a2-34be-45aa-93bb-8f967682e27d","affiliation":"Online Store","revenue":245,"tax":"5.00","shipping":"5.00","action":"purchase"},"products":[{"id":"9bdd2","name":"Compton T-Shirt","price":"44.00","brand":"Compton","category":"T-Shirts","variant":"red","dimension1":"M","position":0,"quantity":1},{"id":"bc823","name":"Fuelworks T-Shirt","price":"92.00","brand":"Fuelworks","category":"T-Shirts","variant":"red","dimension1":"M","position":1,"quantity":1},{"id":"6c3b0","name":"Zappix T-Shirt","price":"99.00","brand":"Zappix","category":"T-Shirts","variant":"red","dimension1":"M","position":2,"quantity":1}]}},"gtm.uniqueEventId":16}]

以下サイトにて上記JSON配列を見やすい状態に整形して見ることができる。
JSONMate - JSON editor, inspector and beautifier


コード

目的のkey-valueペアを持つdataLayerのみを抽出するコード

以下サンプルコード内の即時関数の第一引数にdataLayer変数、第二引数にオブジェクト形式で表した目的のkeyとvalueのペアのリストを入力することにより、条件に合うdataLayerのデータのみを抽出するコード。
このサンプルコードでは、以下条件にマッチするデータを抽出している。

  • keyとしてecommerceを持っているデータ(ecommerceの値については未指定=undefined
filterDataLayer.js
(function(dl, filters){
  var filteringDl = function(dl, key, val){
    dl = dl.slice(0);
    for(var i = 0; i < dl.length; i++){
      if(!dl[i].hasOwnProperty(key) || (typeof(val) !== 'undefined' && dl[i][key] !== val)){
        dl.splice(i, 1);
        i--;
      }
    }
    return dl;
  };
  dl = dl.slice(0);
  if(typeof filters !== 'undefined'){
    for(var filter in filters){
      dl = filteringDl(dl, filter, filters[filter]);
    }
  }
  return dl;
})(window.dataLayer, {'ecommerce': undefined});

image.png

第二引数内の要素を増やすことにより、key-valueペア条件を複数設定することもできる。
以下サンプルコードでは、以下のすべての条件にマッチするデータを抽出している。

  • keyとしてecommerceを持っているデータ(ecommerceの値については未指定=undefined
  • keyとしてeventを持っており、その値はcheckoutであるデータ
filterDataLayer.js
(function(dl, filters){
  var filteringDl = function(dl, key, val){
    dl = dl.slice(0);
    for(var i = 0; i < dl.length; i++){
      if(!dl[i].hasOwnProperty(key) || (typeof(val) !== 'undefined' && dl[i][key] !== val)){
        dl.splice(i, 1);
        i--;
      }
    }
    return dl;
  };
  dl = dl.slice(0);
  if(typeof filters !== 'undefined'){
    for(var filter in filters){
      dl = filteringDl(dl, filter, filters[filter]);
    }
  }
  return dl;
})(window.dataLayer, {'ecommerce': undefined, 'event': 'checkout'});

フィルタリング条件が増えたことにより、返ってくるデータ数が少なくなっている。

image.png


dataLayer内の特定のkeyについて、最新のデータを取得するコード

たとえば、dataLayerで最後に発生したeventの値を取得したいときなどに使用できるコード。

GTMの機能を利用する方法

コード中のGTM-XXXXXXの箇所を稼働中のGTMのコンテナIDに置換えて、get()の引数に目的のdataLayerのkey値を代入して使用する。
但しGTMに依存したやり方になるため、何らかの理由でGTMタグが正常に読み込まれなかったときはこのコードも稼働しなくなる。

以下、サンプルコードでは、ecommerceのデータを取得している。

getValfromDataLayerGTM.js
google_tag_manager['GTM-XXXXXX'].dataLayer.get('ecommerce');

更にその奥にあるデータを取得したいときは以下の要領でコードを実行する。

getValfromDataLayerGTM.js
google_tag_manager['GTM-XXXXXX'].dataLayer.get('ecommerce')['purchase']['products'];

image.png

GTMに依存しない方法

以下コード内の即時関数の第一引数にdataLayer変数、第二引数に目的のkey値、第三引数に欲しいデータにたどり着くまでのkey値を配列によって羅列することにより、目的のdataLayerの値を取得することができる。
第三引数は任意なので省略可能。空の配列[]でも可。

getValfromDataLayer.js
(function(dl, key, path){
  var hasChild = function(){
    for(var i = 0, len = arguments.length; i < len; i++){
      if(typeof arguments[i] === 'undefined' || arguments[i].constructor !== Object){
        return false;
      }
    }
    return true;
  };
  var merge = function(base, add){
    if(hasChild(base, add) && base.constructor === add.constructor){
      for(var k in add){
        if(hasChild(base[k], add[k]) && base[k].constructor === add[k].constructor) {
            merge(base[k], add[k]);
        }else{
          base[k] = add[k];
        }
      }
    }else{
      base = add;
    }
    return base;
  };

  dl = dl.slice(0);
  var ret = {};
  for(var i = 0, len = dl.length; i < len; i++){
    if(dl[i].hasOwnProperty(key)){
      ret = merge(ret, dl[i][key]);
    }
  }
  if(typeof ret === 'object' && Object.keys(ret).length === 0){
    return undefined;
  }
  if(typeof path !== 'undefined'){
    for(var i = 0, len = path.length; i < len; i++){
      ret = ret[path[i]];
    }
  }
  return ret;
})(window.dataLayer, 'ecommerce', ['purchase', 'products']);

image.png

第三引数の「欲しいデータにたどり着くまでのkey値」は不要であれば省略可能。

image.png

GTM版のコードとは若干動作を変えており、目的のキー値に対応するすべての最新のデータを取得できるようにしている。

以下画像の左側がGTM版のコード動作結果、右側がGTM非依存のオリジナルコードの動作結果。
非依存版の方がアクセスできる情報が多い。

image.png

小話「dataLayer変数を宣言するとき」

Webマーケティング担当者など、JavaScriptにあまり詳しくない方向けの推奨方法。

dataLayer変数はグローバルスコープ(window)で使用することを想定されたものなので、varを付けて宣言してしまうと、dataLayerを宣言するコードの場所によってはGTMから内容を見ることができないことがある。
コーディングルール上特に差し障りが無いのであれば、明示的にvar無しで、代わりにwindow.dataLayerとすることによりグローバル変数として宣言することが望ましい。

JavaScriptでのグローバル変数の宣言方法 | UX MILK

badDeclareDataLayer.js
var dataLayer = [{
  "ecommerce": {
    "currencyCode": "USD",
    "impressions": [{
      "id": "9bdd2",
      "name": "Compton T-Shirt",
      "price": "44.00",
      "brand": "Compton",
      "category": "T-Shirts",
      "position": 0,
      "list": "homepage"
    },
    {
      "id": "f6be8",
      "name": "Comverges T-Shirt",
      "price": "33.00",
      "brand": "Comverges",
      "category": "T-Shirts",
      "position": 1,
      "list": "homepage"
    }]
  }
}];

↓やや改善

goodDeclareDataLayer1.js
window.dataLayer = [{
  "ecommerce": {
    "currencyCode": "USD",
    "impressions": [{
      "id": "9bdd2",
      "name": "Compton T-Shirt",
      "price": "44.00",
      "brand": "Compton",
      "category": "T-Shirts",
      "position": 0,
      "list": "homepage"
    },
    {
      "id": "f6be8",
      "name": "Comverges T-Shirt",
      "price": "33.00",
      "brand": "Comverges",
      "category": "T-Shirts",
      "position": 1,
      "list": "homepage"
    }]
  }
}];

上記コードは最初のコードより やや改善されたが、まだ問題が残っている。
具体的には、今の書き方だと既に他のコードによりdataLayer変数が宣言されていた場合、既存のdataLayer変数内のデータをすべて上書き消去してしまうことになる。

これを回避するにはdataLayer変数を宣言する際、「既にdataLayer変数が宣言してあればそれを使う」という意味の書き方を使用する。
また、dataLayer変数へのデータの登録は、変数宣言と同時に行おうとせずに常にdataLayer.push()で行うようにすると安全。

goodDeclareDataLayer2.js
window.dataLayer = window.dataLayer || [];

dataLayer.push({
  "ecommerce": {
    "currencyCode": "USD",
    "impressions": [{
      "id": "9bdd2",
      "name": "Compton T-Shirt",
      "price": "44.00",
      "brand": "Compton",
      "category": "T-Shirts",
      "position": 0,
      "list": "homepage"
    },
    {
      "id": "f6be8",
      "name": "Comverges T-Shirt",
      "price": "33.00",
      "brand": "Comverges",
      "category": "T-Shirts",
      "position": 1,
      "list": "homepage"
    }]
  }
});

「dataLayer」「変数のスコープ」の意味をよく分かっていない人ほど このやり方を使用することをオススメ。

その他参考になるリンク

dataLayer

拡張eコマース