GoogleAnalytics
GoogleTagManager
EC-CUBE3

ECサイト制作者向けGoogleアナリティクス基本ガイド(EC-CUBE 3.0の実装サンプルコードあり)

本記事ではGoogleアナリティクスの拡張eコマースを使ったECサイトのトラッキングの基本をご紹介します。前半で拡張eコマースの概要をご紹介し、後半でEC-CUBE3の実装例をご紹介します。

拡張eコマースの概要

Googleアナリティクスではeコマースの設定を有効にすることで、ecサイトにおけるユーザーの行動と購買情報を分析することができます。

tmp.gif

下の図は通常のeコマースと拡張eコマースのメニューを比較したものです。通常のeコマースと拡張eコマースではメニューの内容が異なります。また、マーケティングというメニューが追加されます。

tmp.gif

ここでは拡張eコマースのメニューについて簡単にご紹介します。なお、サンプルの画面はデモアカウント(Google Merchandise store)のデータを使用していますので金額がドル表示になっています。

:chart_with_upwards_trend: 概要

tmp.gif

概要では以下の項目を確認することができます。

:scales: 収益

全ての注文を合計したサイト全体の販売収益を表します。

:scales: eコマースのコンバージョン率

ユーザー(セッション)の何%が注文に至ったのかを表します。

eコマースのコンバージョン率 = (トランザクション数 / 総セッション数) × 100

:scales: トランザクション数

ユーザーからの注文件数を表します。

:scales: 平均注文額

1回の注文あたりの販売収益になります。

平均注文額 = 全体の収益 / トランザクション数

:scales: キャンペーン

PPC広告やメール、ソーシャルメディアなどのマーケティングキャンペーンで集客したユーザーのトランザクション数や収益、平均注文額を表します。キャンペーンを計測するにはキャンペーン パラメータ(utm_source、utm_medium、utm_campaign など)付きのURLを使用する必要があります。

:scales: サイト内プロモーション

自サイト内に設置するプロモーションバナーやLPといったクリエイティブの表示回数を表します。

:scales: オーダークーポンコード

お買い物金額から1000円OFFといったトランザクション全体に適用するクーポンのことを表します。Googleアナリティクスではトランザクション全体に適用するオーダークーポン以外に、商品ごとに適用する商品クーポンのデータも計測することができます。

:scales: アフィリエーション

トランザクションの発生源となったショップまたは提携サイトを表します。もし提携サイト(アフィリエイトサイト)から集客を行っているのであれば、アフィリエイトコードを設定することでサイト毎の収益やトランザクション数を確認することができます。

:chart_with_upwards_trend: ショッピング行動

tmp.gif

ショッピング行動では、商品表示 ⇒ カート追加 ⇒ 購入手続き ⇒ 決済完了という購入プロセスの流れを数値で確認することができます(あるステップから次のステップへと至ったセッションの数や各段階におけるプロセスの放棄回数)。

各段階の数値には途中のプロセスから開始したユーザーのセッションも含まれます(例えば、ユーザーが 商品表示 ⇒ カート追加 と進んで一旦サイトを離れ、その後別のセッションで前回のカートの中身のまま購入手続きに進んだ場合など)。

tmp.gif

ショッピング行動では様々なセグメントに絞って購入プロセスをチェックできますので、モバイルに絞ってモバイルユーザーのカゴ落ちを把握するなど、コンバージョンに影響を及ぼしているプロセスがないかどうかチェックすると良いでしょう。

:chart_with_upwards_trend: 決済行動

tmp.gif

決済行動では、設定した決済目標到達プロセス(例:配送情報入力 ⇒ カード情報入力 ⇒ 決済)の流れを数値で確認することができます。前述したショッピング行動でチェックアウトの放棄が多いようであれば、決済行動でより詳しくボトルネックを調査することができます。

:chart_with_upwards_trend: 商品の販売状況

tmp.gif

商品の販売状況では以下の項目を確認することができます。

:scales: 商品の収益

各商品の販売収益を表します。前述した概要の収益は割引などを含めて自由に設定できましたが、こちらは送信した単価と数量から算出されます(サイトによっては概要の収益と商品の収益が一致しない場合がある)。

:scales: 固有の購入数

固有の購入数は、例えば一人のユーザー(セッション)がA、B、Cという異なる3つの商品を購入した場合、固有の購入数は3となります。つまりトランザクション数が542で固有の購入数の合計値が1038だとすると、1注文あたり約1.9種類の商品が購入されていることになります。1つの商品の固有の購入数が60だった場合、その商品は60のトランザクションで購入されたことを表します。

1注文あたりの固有の購入数が少ないようであれば、クロスセル(関連商品の販売)やセット割引など、ユーザーの複数購入を後押しする販促を実施してみると良いかもしれません。

:scales: 数量

トランザクション全体で購入された商品の数量を表します。1つのトランザクションで複数個購入する場合がありますので数量 >= 固有の購入数となります。

:scales: 平均価格

商品の収益を数量で割ったものになります。

平均価格 = 商品収益 / 数量

:scales: 平均数量

1つのトランザクションで購入された数量の平均を表します。つまり、平均数量は数量を固有の購入数で割ったものになります。

平均数量 = 数量 / 固有の購入数

商品ごとに平均数量を見れば、どの商品がよくまとめ買いされているのかが把握できます。売れ筋の商品だけでなく、まとめ買いされやすい商品というのを把握しておけば、より効果的な販促計画を立てられると思います。

:scales: 商品の払い戻し額

商品の払い戻し額はユーザーに返金した金額になります。refundのデータを送信することで返金した金額を反映することができます。ただし、対象となるトランザクションが報告された日付から6ヶ月以内の場合にのみデータを送信することができます。

:scales: Cart-to-Detail率

商品のカートへの追加回数を商品の詳細情報の閲覧回数で割った値になります。

Cart-to-Detail率 = (商品のカートへの追加回数 / 商品の詳細情報の閲覧回数) × 100

:scales: Buy-to-Detail率

Buy-to-Detail率とは、商品の購入回数を商品の詳細情報の閲覧回数で割った値になります。

Buy-to-Detail率 = (商品の購入回数 / 商品の詳細情報の閲覧回数) × 100

:scales: 商品のSKU

SKU(Stock Keeping Unit)は商品の最小管理単位を表します。洋服であれば「Qiitaマーク Tシャツ カラーホワイト サイズM」のような在庫管理単位になるでしょう。

tmp.gif

:pushpin: tips

商品の販売状況は商品の他に、商品のSKU、商品のカテゴリ、商品ブランドの計4つのディメンションで画面を切り替えることができます。例えば商品のカテゴリでピボットテーブルを使ってメディア毎に商品の収益を確認するといったような使い方ができます。SEOやPPCなどの計画を立てる際には前年実績と見比べながら予算配分を考えると良いでしょう。

tmp.gif

:chart_with_upwards_trend: 販売実績

tmp.gif

販売実績では以下の項目を確認することができます。

:scales: トランザクションID

トランザクションIDはトランザクションを識別する固有のIDです。システムでオーダー番号のようなものを付けているのであれば、それがトランザクションIDに該当するでしょう。1回の注文で複数の商品を購入した場合、1つのトランザクションIDでそれらの購入をまとめる形になります。

tm.gif

:scales: 収益、税金、配送、払い戻し額、数量

トランザクション単位での収益、税金、配送料、払い戻し額、数量を表します。

:chart_with_upwards_trend: 商品リストの販売状況

tmp.gif

拡張eコマースでは商品のインプレッションデータを送信する際に、オプションとして任意の商品リスト名(例:カタログページ、おすすめ商品、関連商品 など)を付けることができます。これを利用して、商品のインプレッションが発生した場所を識別することができます。

:scales: 商品リストの閲覧回数

商品リストに表示された商品をユーザーが閲覧した回数を表します。

:scales: 商品リストのクリック数

商品リストに表示された商品をユーザーがクリックした回数を表します。

:scales: 商品リストのクリック率

商品リストを閲覧したユーザーの何%が商品リストをクリックしたのかを表します。

商品リストのクリック率 = (商品リストのクリック数 / 商品リストの閲覧回数) × 100

:scales: 商品がカートに追加された回数

商品リストに表示された商品をユーザーがカートに追加した回数を表します。

:scales: 商品の決済回数

商品リストに表示された商品をユーザーがカートに追加し、決済手続きに進んだ回数を表します。

:scales: 固有の購入数

商品リストに表示された商品が購入された数量を表します。

:scales: 商品の収益

商品リストに表示された商品が購入されて発生した収益を表します。

:pushpin: tips

商品リストの販売状況は商品リスト名の他に、商品リスト位置、商品、商品のSKUの計4つのディメンションで画面を切り替えることができます。例えばプライマリディメンションを商品、セカンダリディメンションを商品リスト位置に設定し、各商品の成果をそれぞれのリスト位置と照らし合わせて確認すれば、リスト内で下位にあるにも関わらず上位の商品よりも高い成果を上げているものを見つけることができるかもしれません。このような成果の高い商品を目立つ位置に移動すれば、より大きな成果を期待できます。

tmp.gif

拡張eコマースのデータの種類

前述した表やグラフを確認するにはGoogleアナリティクスにeコマースのデータを送信する必要があります。拡張eコマースで送信できるデータは以下の4種類です。

  • インプレッション データ
  • 商品データ
  • プロモーション データ
  • アクション データ

:one: インプレッション データ

インプレッション データは閲覧された商品に関する情報を表すもので、商品情報を含むview_item_listイベントを送信してインプレッションを計測します。イベントで送信できるインプレッション データは以下の通りです。

キー 必須 説明
id string 商品を識別する固有のID(SKU)
name string 商品名
category string 商品が属するカテゴリ。区切り文字「/」を使って最大5レベルの階層を指定可
brand string 商品のブランド
variant string 商品のバリエーション
list_name string 商品リスト名
list_position integer リストにおける商品の掲載順位
price currency 商品の価格

※idとnameはどちらか片方だけの送信でも可

view_item_listイベントの実装例は以下のようになります。

gtag('event', 'view_item_list', {
  'items': [
    {
      'id': '499904',
      'name': 'Qiitaマーク Tシャツ',
      'category': 'アパレル/Tシャツ',
      'brand': 'Qiita',
      'variant': 'ホワイト',
      'list_name': '商品一覧',
      'list_position': 8,
      'price': '2080'
    }
  ]
});

:two: 商品データ

商品データは閲覧されたり、カートに追加された商品などの情報を表すもので、以下のいずれかのイベントを送信して計測を行います。

イベント 説明
select_content 商品リンクのクリック
view_item 商品情報の表示
add_to_cart カートへの商品追加
remove_from_cart カートからの商品削除

イベントで送信できる商品データは以下の通りです。

キー 必須 説明
id string 商品を識別する固有のID(SKU)
name string 商品名
category string 商品が属するカテゴリ。区切り文字「/」を使って最大5レベルの階層を指定可
brand string 商品のブランド
variant string 商品のバリエーション
price currency 商品の価格
quantity integer 商品の数
coupon string 商品に設定されているクーポンコード
list_position integer リストにおける商品の掲載順位

※idとnameはどちらか片方だけの送信でも可

select_contentイベントの実装例は以下のようになります。

// 検索結果の商品リンク クリック時に実行される関数
function onProductClick(product, position) {
  // イベント送信に失敗した場合もリンク先に飛ぶように1秒後に関数を実行
  setTimeout(goTo, 1000); 

  var gone = false;

  var goTo = function() {
    if (!gone) {
      gone = true;
      document.location = '/products/detail/' + product.id;
    }
  }

  gtag('event', 'select_content', {
    'content_type': 'product',
    'list_name': '検索結果',
    'items': [
      {
        'id': product.id,
        'name': product.name,
        'category': product.category,
        'brand': product.brand,
        'variant': product.variant,
        'price': product.price,
        'list_position': position
      }
    ],
    'event_callback': function() {
      goTo();
    }
  });
}

view_itemイベントの実装例は以下のようになります。

gtag('event', 'view_item', {
  'items': [
    {
      'id': '499904',
      'name': 'Qiitaマーク Tシャツ',
      'category': 'アパレル/Tシャツ',
      'brand': 'Qiita',
      'variant': 'ホワイト',
      'price': '2080'
    }
  ]
});

add_to_cartイベントの実装例は以下のようになります。

// カート追加ボタン クリック時に実行される関数
function onCartAddClick(product) {
  // イベント送信に失敗した場合もサブミットされるように1秒後に関数を実行
  setTimeout(doSubmit, 1000); 

  var submitted = false;

  var doSubmit= function() {
    if (!submitted) {
      submitted = true;
      $('#form').submit();
    }
  }

  gtag('event', 'add_to_cart', {
    'items': [
      {
        'id': product.id,
        'name': product.name,
        'category': product.category,
        'brand': product.brand,
        'variant': product.variant,
        'price': product.price,
        'quantity': product.quantity
      }
    ],
    'event_callback': function() {
      doSubmit();
    }
  });
}

remove_from_cartイベントの実装例はadd_to_cartと同じなので割愛します。

:three: プロモーション データ

プロモーション データは閲覧されたプロモーションに関する情報を表すもので、プロモーション情報を含むview_promotionイベントを送信してインプレッションを計測します。イベントで送信できるプロモーション データは以下の通りです。

キー 必須 説明
id string プロモーション ID
name string プロモーションの名前
creative_name string 使用されているクリエイティブの名前
creative_slot string クリエイティブ スロットの名前(掲載場所)

※idとnameはどちらか片方だけの送信でも可

view_promotionイベントの実装例は以下のようになります。

gtag('event', 'view_promotion', {
  'promotions': [
    {
      'id': 'PROMO_1234',
      'name': '2018春キャンペーン',
      'creative_name': '2018_spring_banner_300x250',
      'creative_slot': 'sidebar_rectangle_1'
    }
  ]
});

なお、プロモーション バナーのクリックも計測する場合はselect_contentイベントを使用します。

function onPromotionClick() {
  // イベント送信に失敗した場合もリンク先に飛ぶように1秒後に関数を実行
  setTimeout(goTo, 1000); 

  var gone = false;

  var goTo = function() {
    if (!gone) {
      gone = true;
      document.location = '/user_data/spring_campaign_2018';
    }
  }

  gtag('event', 'select_content', {
    'promotions': [
      {
        'id': 'PROMO_1234',
        'name': '2018春キャンペーン',
        'creative_name': '2018_spring_banner_300x250',
        'creative_slot': 'sidebar_rectangle_1'
      }
    ],
    'event_callback': function() {
      goTo();
    }
  });
}

:four: アクション データ

アクション データは決済プロセスに関する情報を表すもので、以下のいずれかのイベントを送信して計測を行います。

イベント 説明
begin_checkout 決済プロセスの開始
checkout_progress 決済プロセスの各ステップ
set_checkout_option 任意の決済ステップに対するオプション値の送付
purchase 商品の販売
refund 商品の払い戻し

イベントで送信できるアクション データは以下の通りです。

キー 必須 説明
transaction_id string トランザクションの一意の ID
affiliation string このトランザクションの発生源となったショップまたは提携サイト
value currency 収益額。値が設定されなかった場合、同じヒットのすべての商品の数量と価格を使って自動計算
tax currency 税額
shipping currency 送料
items array 関連する商品を含む配列
checkout_step integer 決済プロセスのステップを表す番号
checkout_option string 決済オプション(選択された支払い方法)
coupon string オーダークーポンコード

begin_checkoutイベントの実装例は以下のようになります。

gtag('event', 'begin_checkout', {
  'items': [
    {
      'id': '499904',
      'name': 'Qiitaマーク Tシャツ',
      'category': 'アパレル/Tシャツ',
      'brand': 'Qiita',
      'variant': 'ホワイト',
      'price': '2080'
    }
  ],
  'coupon': 'SPRING2018'
});

checkout_progressイベントの実装例は以下のようになります。

gtag('event', 'checkout_progress', {
  'checkout_step': 2,
  'items': [
    {
      'id': '499904',
      'name': 'Qiitaマーク Tシャツ',
      'category': 'アパレル/Tシャツ',
      'brand': 'Qiita',
      'variant': 'ホワイト',
      'price': '2080'
    }
  ],
  'coupon': 'SPRING2018'
});

set_checkout_optionイベントの実装例は以下のようになります。

gtag('event', 'set_checkout_option', {
  'checkout_step': 2,
  'checkout_option': 'payment method',
  'value': 'Credit Card'
});

purchaseイベントの実装例は以下のようになります。

gtag('event', 'purchase', {
  'transaction_id': '1234',
  'affiliation': 'Qiita Shop',
  'value': '2080',
  'tax': '166',
  'shipping': '1000', 
  'items': [
    {
      'id': '499904',
      'name': 'Qiitaマーク Tシャツ',
      'category': 'アパレル/Tシャツ',
      'brand': 'Qiita',
      'variant': 'ホワイト',
      'price': '2080'
    }
  ],
  'coupon': 'SPRING2018'
});

refundイベントの実装例は以下のようになります。

gtag('event', 'refund', { 'transaction_id': '1234' });

もし一部の商品だけ払い戻しする場合には、対象商品のデータと一緒に送信します。

gtag('event', 'refund', {
  'transaction_id': '1234',
  'value': '2080',
  'tax': '166',
  'shipping': '0', 
  'items': [
    {
      'id': '499904',
      'name': 'Qiitaマーク Tシャツ',
      'category': 'アパレル/Tシャツ',
      'brand': 'Qiita',
      'variant': 'ホワイト',
      'price': '2080'
    }
  ]
});

EC-CUBEへの実装

拡張eコマースのデータのいつくかをEC-CUBEに実装してみたいと思います。なお、本記事はEC-CUBEのカスタマイズが主題ではありませんので、非常に簡易的な実装です。ここで書かれているコードをそのまま利用せずに、サイトに合わせてしっかりと設計を行った上で実装してください。

:zero: eコマースの設定を行う

まず拡張eコマースを使用するための設定を行う必要があります。「管理」⇒「ビュー」⇒「eコマースの設定」で拡張eコマースのレポートを有効にしてください。また、目標到達プロセスのステップの設定も行ってください。ここでは「お客様情報の入力」と「ご注文内容の確認」をステップに設定しています。

tmp.gif

:one: トラッキング コードを設置する

今回はグローバル サイトタグ(gtag.js)を使います。トラッキング コードを取得したらEC-CUBEの管理画面でトラッキング コード用のブロックを作成してください。

tmp.gif

ブロックを作成したらhead内に設置してください。

tmp.gif

:warning: 既にGoogleタグマネージャを設置していて、グローバル サイトタグと併用したいという場合もあるかと思います。そのままトラッキングコードを設置すると、Googleタグマネージャでページビューを計測している場合にページビューを重複してカウントしてしまうことになります。その場合は、トラッキングコードを以下のように修正してください。

gtag('config', 'UA-xxxxxxxxx-x'); // 修正前

gtag('config', 'UA-xxxxxxxxx-x', { 'send_page_view': false }); // 修正後

:two: 商品一覧のインプレッションとクリックを計測する

http://xxxxxxxxxxx/products/list?category_id=1のようなカテゴリ一覧ページで、表示された商品のインプレッションおよび商品リンクのクリックを計測します。

tmp.jpg

EC-CUBEの管理画面のページ管理から商品一覧ページ(Product/list.twig)を編集します。テンプレートのJavaScriptのブロックにインプレッションを計測する以下のスクリプトを追加します。ここではidに商品コード、variantに規格1、priceに販売価格を設定しています。一つの商品で複数の商品コード、規格、価格を持つ場合がありますので、便宜的にその内の一つを設定していますが、複数ある商品は必須項目だけ設定して、任意項目は無理に設定しなくても良いかと思います。

var items = [];
{% for Product in pagination %}
{%- set productClass = Product.productClasses|first -%}
items.push({
  'id': '{{ Product.codeMin }}',
  'name': '{{ Product.name }}',
  'category': '{{ Category.name }}',
  {% if productClass.classCategory1 is not null -%}
  'variant': '{{ productClass.classCategory1.name }}',
  {% endif -%}
  'list_name': '商品一覧',
  'list_position': {{ loop.index }},
  'price': '{{ Product.price02Min }}'
});
{% endfor %}

gtag('event', 'view_item_list', {
  'items': items
});

スクリプトを追加したら保存して画面を確認してみましょう。確認する際はChromeのGoogle Tag Assistantを使ってレコーディングしてください。view_item_listのイベントが記録され、以下のような内容が表示されることを確認してください。

tmp.gif

次に商品リンクのクリックを実装します。再度ページ管理から商品一覧ページの編集画面を開き、JavaScriptのブロックに以下のスクリプトを追加します。

function onProductClick(index, path) {
  setTimeout(goTo, 1000);

  var gone = false;

  var goTo = function() {
    if (!gone) {
      gone = true;
      document.location = path;
    }
  }

  gtag('event', 'select_content', {
    'content_type': 'product',
    'list_name': '商品一覧',
    'items': [
      items[index - 1]
    ],
    'event_callback': function() {
      goTo();
    }
  });
}

次に同じテンプレート内の商品一覧を表示している部分で、アンカータグにonclickイベントを追加して先程の関数を呼び出すようにします。

{% for Product in pagination %}
<div id="result_list_box--{{ Product.id }}" class="col-sm-3 col-xs-6">
  <div id="result_list__item--{{ Product.id }}" class="product_item">
    <a href="javascript:void(0);" onclick="javascript:onProductClick({{ loop.index }}, '{{ url('product_detail', {'id': Product.id}) }}')">

テンプレートを保存したらGoogle Tag Assistantを使って確認してみましょう。リンクをクリックしてselect_contentイベントに以下のような内容が記録されていることを確認してください。

tmp.gif

:three: 商品情報の閲覧、カートへの追加を計測する

先程リンクのクリックを計測しましたが、次はその遷移先の商品情報ページの閲覧を計測します。

tmp.jpg

ページ管理から商品詳細ページ(Product/detail.twig)を編集します。テンプレートのJavaScriptのブロックにインプレッションを計測する以下のスクリプトを追加します。ここでも一覧ページと同じように一つの商品で複数の商品コード、規格、価格を持つ場合がありますので、便宜的にその内の一つを設定しています。

gtag('event', 'view_item', {
  'items': [
    {
      'id': '{{ Product.codeMin }}',
      'name': '{{ Product.name }}',
      'category': '{{ productCategory.category.name }}',
      {% if productClass.classCategory1 is not null -%}
      'variant': '{{ productClass.classCategory1.name }}',
      {% endif -%}
      'price': '{{ Product.price02Min }}'
    }
  ]
});

テンプレートを保存したらGoogle Tag Assistantを使って確認してみましょう。画面を表示してview_itemイベントに以下のような内容が記録されていることを確認してください。

tmp.gif

次にカートへの追加を実装します。再度ページ管理から商品詳細ページの編集画面を開き、JavaScriptのブロックに以下のスクリプトを追加します。

function onCartAddClick(item) {
  setTimeout(doSubmit, 1000);

  var submitted = false;

  var doSubmit = function() {
    if (!submitted) {
      submitted = true;
      $('#form1').submit();
    }
  }

  gtag('event', 'add_to_cart', {
    'items': [
      {
        'id': item.product_code,
        'name': '{{ Product.name }}',
        'category': '{{ productCategory.category.name }}',
        {% if productClass.classCategory1 is not null -%}
        'variant': $('#classcategory_id1 option:selected').text(),
        {% endif -%}
        'price': item.price02.replace(/,/g, ''),
        'quantity': $('#quantity').val()
      }
    ],
    'event_callback': function() {
      doSubmit();
    }
  });
}

さらにカート追加ボタンのクリックイベント時の処理に、先程の関数を呼び出す処理を追加します。eccube.classCategoriesにはその製品の商品コード、販売価格の一覧が格納されていますので、セレクトボックスで選択された規格の商品コードと販売価格をそこから取得しています。

$('#add-cart').click(function() {
  $('#mode').val('add_cart');

  var _id1 = $('#classcategory_id1').val();
  var _id2 = $('#classcategory_id2').val();
  if (_id1) {
    onCartAddClick(eccube.classCategories[_id1]['#' + _id2]);
  } else {
    onCartAddClick(eccube.classCategories['__unselected2']['#']);
  }
});

テンプレートを保存したらGoogle Tag Assistantを使って確認してみましょう。カート追加ボタンをクリックしてadd_to_cartイベントに以下のような内容が記録されていることを確認してください。

tmp.gif

:warning: 商品リストの販売状況のレポートを見ると商品リスト名に(not set)でカートへの追加がカウントされている場合があります。

tmp.gif

本記事の実装では商品一覧ページで、複数の商品コード、規格、価格を持つ商品は便宜的にその内の一つを設定して、view_item_listイベントやselect_contentイベントを送信しました。しかし、商品情報ページで設定したものと異なる商品コードの商品を選択してカートに追加すると上記のような現象が発生します。

tmp.gif

公式ガイドで情報を見つけることが出来なかったので確かなことは言えませんが、商品リストの閲覧と商品リンクのクリックで送信した商品データのidと、カート追加で送信する商品データのidが一致していないと別のものとして扱われるようです。

:four: 決済プロセスを計測する

カートに追加するところまで計測しましたので、最後に決済プロセスを計測してみたいと思います。今回はユーザー登録なしのゲスト購入のプロセスのみ実装します。

tmp.gif

まずは、お客様情報の入力を決済プロセスの開始点として計測します。ブロック管理画面で決済プロセスの開始を計測するためのブロックを作成します。ブロックの中身は以下のようになります。

<script type="text/javascript">
gtag('event', 'begin_checkout', {
  'items': [
  {% set Cart = app['eccube.service.cart'].getCartObj %}
  {% for CartItem in Cart.CartItems %}
  {% set ProductClass = CartItem.Object %}
  {% set Product = ProductClass.Product %}
  {% set ProductCategory = Product.productCategories|first %}
    {
      'id': '{{ ProductClass.code }}',
      'name': '{{ Product.name }}',
      'category': '{{ ProductCategory.category.name }}',
      {% if ProductClass.classCategory1 is not null -%}
      'variant': '{{ ProductClass.classCategory1.name }}',
      {% endif -%}
      'quantity': {{ CartItem.quantity }},
      'price': '{{ CartItem.price }}'
    },
  {% endfor %}
  ],
  'coupon': 'SPRING2018'
});
</script>

ブロックを作成したらページ管理で非会員購入情報入力画面(ルート名:shopping_nonmember)のレイアウトを編集し、先程作成したブロックを追加します。

tmp.gif

レイアウトの編集が完了したらGoogle Tag Assistantを使って確認してみましょう。ページを開いてbegin_checkoutイベントに以下のような内容が記録されていることを確認してください。

tmp.gif

次にご注文内容の確認を決済プロセスの2ステップ目として計測します。ブロック管理画面で決済プロセスのステップを計測するためのブロックを作成します。ブロックの中身は以下のようになります。

<script type="text/javascript">
gtag('event', 'checkout_progress', {
  'checkout_step': 2,
  'items': [
  {% set Cart = app['eccube.service.cart'].getCartObj %}
  {% for CartItem in Cart.CartItems %}
  {% set ProductClass = CartItem.Object %}
  {% set Product = ProductClass.Product %}
  {% set ProductCategory = Product.productCategories|first %}
    {
      'id': '{{ ProductClass.code }}',
      'name': '{{ Product.name }}',
      'category': '{{ ProductCategory.category.name }}',
      {% if ProductClass.classCategory1 is not null -%}
      'variant': '{{ ProductClass.classCategory1.name }}',
      {% endif -%}
      'quantity': {{ CartItem.quantity }},
      'price': '{{ CartItem.price }}'
    },
  {% endfor %}
  ],
  'coupon': 'SPRING2018'
});
</script>

ブロックを作成したらページ管理で商品購入画面(ルート名:shopping)のレイアウトを編集し、先程作成したブロックを追加します。

tmp.gif

レイアウトの編集が完了したらGoogle Tag Assistantを使って確認してみましょう。ページを開いてcheckout_progressイベントに以下のような内容が記録されていることを確認してください。

tmp.gif

最後に注文完了を計測します。ブロック管理画面で注文完了を計測するためのブロックを作成します。ブロックの中身は以下のようになります。ここでは収益を送料と消費税込みで計算しています。

<script type='text/javascript'>
{% set orderId = app.session.get('orderId') %}
{% set Order = app['eccube.repository.order'].find(orderId) %}
gtag('event', 'purchase', {
  'transaction_id': '{{ orderId }}',
  'affiliation': 'きーた家具店',
  'value': '{{ Order.PaymentTotal }}',
  'tax': '0',
  'shipping': '0',
  'items': [
  {% set OrderDetails = Order.OrderDetails %}
  {% for OrderDetail in OrderDetails %}
  {% set ProductClass = OrderDetail.ProductClass %}
  {% set Product = OrderDetail.Product %}
  {% set ProductCategory = Product.productCategories|first %}
    {
      'id': '{{ OrderDetail.ProductCode }}',
      'name': '{{ OrderDetail.ProductName }}',
      'category': '{{ ProductCategory.category.name }}',
      {% if ProductClass.classCategory1 is not null -%}
      'variant': '{{ ProductClass.classCategory1.name }}',
      {% endif -%}
      'quantity': {{ OrderDetail.Quantity }},
      'price': '{{ OrderDetail.Price }}'
    },
  {% endfor %}
  ],
  'coupon': 'SPRING2018'
});
</script>

また、オーダーIDを渡すためにShoppingControllerのcompleteアクションにオーダーIDをセッションに格納する処理を追加しています(今回は簡易的な実装のためコアファイルを修正していますが、イベントリスナーを使うなどコアファイルを修正しない方法もあります)。

Eccube\Controller\ShoppingController.php
public function complete(Application $app, Request $request)
{

  $app['session']->set('orderId', $orderId);

} 

ブロックを作成したらページ管理で商品購入/ご注文完了画面(ルート名:shopping_complete)のレイアウトを編集し、先程作成したブロックを追加します。

tmp.gif

レイアウトの編集が完了したらGoogle Tag Assistantを使って確認してみましょう。ページを開いてpurchaseイベントに以下のような内容が記録されていることを確認してください。

tmp.gif

以上で決済プロセスの計測は終了です。

その他ポイント

ここまで拡張eコマースを中心にご紹介しましたが、それ以外で抑えておきたいポイントをいくつかピックアップしてご紹介します。

ユーザーリスト(リマーケティングリスト)

Google ディスプレイ ネットワーク(GDN)でリマーケティング広告を配信する場合、Google Adwordsのオーディエンスマネージャを使ってターゲットとなるユーザーのリストを作ることができます。

tmp.gif

リストに設定できる条件には以下のようなものがあります。

  • 特定のページを訪問したユーザー
  • 特定のページのみを訪問したユーザー
  • 異なる2つのページを訪問したユーザー
  • 特定の期間内にページを訪問したユーザー
  • 特定のタグが設定されたページを訪問したユーザー

しかし、サイトによってはこれよりもっと細かくターゲットを絞りたい場合があるかもしれません。そのような場合はGoogleアナリティクスのユーザーリストを使うと良いでしょう。こちらはアナリティクスのデータをそのまま利用できるため、さらにコンテキストを意識した広告配信ができるようになります。

例えばファッション通販サイトであれば以下のようなリストが考えられるでしょう。

  • 特定のブランドのシューズを1回のセッションで1万円以上購入したユーザー
  • メンズのジーンズをカートに追加したことがあるユーザー
  • キャンペーンメールから集客したユーザー
  • コーディネートに関するコンテンツを1分以上閲覧したユーザー

ユーザーリストを作成するには、まず「管理⇒プロパティ⇒AdWordsのリンク設定」でAdWordsのアカウントをリンクしてください。リンクしたら「管理⇒プロパティ⇒ユーザー定義⇒ユーザーリスト」でユーザーリストを作成し、AdWordsへのリンクをクリックすればそのまま広告キャンペーンを作成することができます。

tmp.gif

tmp.gif

tmp.gif

リストは作ってすぐに利用できるものではなく、日々サイトを訪問するユーザーで条件に合致すればリストに追加されていきます。リストの有効期間は1日~540日まで設定可能で、Googleディスプレイ ネットワークで利用するためにはリストの過去30日間のアクティブユーザー数が100人以上、Google 検索ネットワークで利用するためには1000人以上が必要となります。

ライフタイムバリューとコホート分析

顧客獲得コスト(CPA)を設定する上で、ライフタイムバリュー(リピート購入も含めた顧客生涯価値)は重要な要素です。なぜなら、商品の粗利益のみを見てCPAの上限を設定してしまうと、必然的に広告の予算が限られてしまうからです。ライフタイムバリューも加味してCPAを設定すれば広告の選択肢も増え、顧客獲得の機会も増えるでしょう。

顧客のライフタイムバリューは、『1注文あたりの平均額』、『どれくらいの頻度で購入してくれるか(例:1ヶ月に2回)』、『どれくらい継続して購入してくれるか(例:1年)』といった数字から算出することができます。収益ベースでのライフタイムバリューを簡単に表すと以下のようになります。

ライフタイムバリュー = 平均注文額 × 平均購買頻度 × 平均継続期間

もし、手元にデータがなくライフタイムバリューを計算することが難しいのであれば、Googleアナリティクスのライフタイムバリュー レポートを参考にすると良いでしょう。集客後の最初の90 日間のライフタイムバリューを集客チャネル毎に確認することができます。

tmp.gif

売上を上げるためには新規顧客獲得だけでなくライフタイムバリューを向上させる施策が必要になりますが、そのための計画・実行・検証を行う上で役に立つのがGoogleアナリティクスのコホート分析レポートです。

tmp.gif

コホート分析レポートはリテンション(顧客の維持)を分析するためのレポートで、Y軸が集客の日付、X軸が集客した日付から経過した期間、色のついたマスの部分がユーザーの再訪率を表します。

コホート分析レポートはセグメントを絞って確認することが出来ますので、新規ユーザー・リピーターの再訪率、デバイス毎の再訪率、チャネル毎の再訪率、地域毎の再訪率、キャンペーン毎の再訪率、購入した商品ブランドやカテゴリ毎の再訪率など様々なセグメントでチェックしながら、PPC広告やEメールキャンペーン、ソーシャルメディアキャンペーン、コンテンツマーケティングを行ったり、顧客ロイヤリティを高めるための施策を行うと良いでしょう。

リテンション率とライフタイムバリュー、収益の関係性を継続的に観測していけば、リピーターによる収益の見込み、収益目標を達成するために必要な新規顧客獲得数などといった数値もある程度根拠を持って立てられるようになると思います。

マルチチャネルとアトリビューション

ユーザーは様々な経路を経て商品の購入に至ります。例えば古着を買いたいと思ったら最初に「古着+コーデ」のようなキーワードで検索して手掛かりとなるような情報を探す人も多いでしょう。そして、気になるアイテムを見つけたら今度はそのアイテムで検索して商品をピックアップし、「商品名+通販」のようなキーワードで検索して通販サイトを見つけるというパターンはよくあることです。

tmp.gif

このようなユーザー行動の中で、ユーザーとサイトとの接点は検索エンジンやソーシャルメディア、広告、アフィリエイトサイトなどいろいろありますし、初回の接触で必ずしも購入に至る訳ではありません。

もし、全体を見ずに点だけを見てコンバージョンに貢献しているかどうかを判断してしまうと、実際はコンバージョンに貢献しているにも関わらず誤った判断を下してしまう可能性があります。このように直接のコンバージョンだけでチャネルを評価するのではなく、コンバージョンに至る過程での各チャネルの貢献度を知るためのものがマルチチャネル レポートです。

では、実際にデモアカウント(Google Merchandise store)のデータを使ってPPC広告を少し詳しく見てみましょう。まず、最初にコンバージョンのタイプをeコマースのトランザクションだけにし、タイプでAdWordsを選択します。これでeコマースのトランザクションのうち有料広告に関わるものだけに絞り込むことができます。

tmp.gif

コンバージョン概要図を見ると以下のように有料広告とその他のチャネルの関連性が直感的に把握できます。チャネルが重なっている部分はユーザーがコンバージョンに至るまでに接触したチャネルが複数であることを表します。ブルーの有料検索からはみ出している部分がありますが、これはもう一つの有料広告であるディスプレイ広告と関連する部分になります(円の重複範囲はおおよそのものなので完全に正確という訳ではありません)。

tmp.gif

日々の広告運用の中でパフォーマンスに変化があったら広告だけでなくその他のチャネルの変化も併せて見ると良いでしょう。

ここからさらに数値で細かく見たい場合はアシスト コンバージョン レポートを確認します。

tmp.gif

アシスト コンバージョンとは間接的にコンバージョンに貢献したものを表します。コンバージョン経路上の終点以外の位置にあるチャネルは、そのコンバージョンをアシストしたと見なされます。一番右端の数字が1より大きければ大きいほど間接的な貢献が多いチャネル、1より小さければ小さいほど直接的な貢献が大きいチャネルになります。

次に起点の分析に表示を切り替えて確認してみます。

tmp.gif

tmp.gif

そうすると今度は起点として貢献したコンバージョン数を確認することができます。一番右端の数字が1より大きければ大きいほど起点としての貢献が多いチャネル、1より小さければ小さいほど直接的な貢献が大きいチャネルになります。上図を見るとディスプレイ広告はファーストクリックのコンバージョン数は多くありませんが金額の貢献が大きいことが分かるかと思います。

プライマリディメンションを切り替えればさらに多角的に分析することができるでしょう。例えば以下はAdWordsキャンペーン毎のアシスト コンバージョンです。

tmp.gif

カスタムチャネル グループを作成すれば独自のチャネルを定義して分析することもできます。例えばショップ名などの自社ブランド名で広告を出すことはよくありますが、自社ブランド名の広告をチャネルとして定義し貢献度を把握するような使い方が考えられるでしょう。

tmp.gif

tmp.gif

他にもランディングページURLを指定して、バーチャルコーディネートのようなオンライン ツール、動画やロングフォーム コンテンツといったリードジェネレーションのためのコンテンツがどれくらいコンバージョンに貢献しているかを把握するような使い方も考えられます。

カスタムチャネル グループに加えてコンバージョン セグメントも併用するとさらに細かく分析することができます。こちらはコンバージョン経路を条件にしてデータを絞り込むことができます。

tmp.gif

例えば、SEOやPPC広告がダイレクト トラフィックによるコンバージョンにどれくらい貢献しているのか気になる方も多いでしょう。そのような場合、コンバージョンセグメントで「終点がノーリファラーのセグメント」を選択することでSEOやPPC広告がどれくらい貢献しているかを知ることができます。

tmp.gif

tmp.gif

セカンダリ ディメンションに「キャンペーン」を選択してアドバンス フィルタで絞り込めばさらに細かく分析することもできます。

tmp.gif

tmp.gif

その他にコンバージョン経路や所用時間、経路の数といったレポートが確認できますので、目的に合わせて併用すると良いでしょう。

ここまでチャネルの貢献度について見てきましたが、コンバージョン経路のどのポイントを評価するかはサイトによって変わってくると思います。例えば以下のようなケースがあったとします。

ユーザーがディスプレイ広告をクリックしてサイトを見つけ、1週間後Facebookでシェアされたリンクをクリックして再びアクセスします。翌日にGoogleでキーワード検索を辿ってサイトを訪れ、同じ日に今度は直接アクセスして商品の購入に至ります。

この場合、ファーストクリックを評価しているのであれば貢献したのはディスプレイ広告ですが、ラストクリックを評価しているのであればダイレクト トラフィックになります。しかし、最後のダイレクト トラフィックを評価したくない場合もあるでしょうし、全てのチャネルを均等に評価したい場合もあるでしょう。

このようにモデルの違いによってチャネルの評価がどのように変化するのかを確認するためのツールがアトリビューションのモデル比較ツールになります。

tmp.gif

アトリビューション モデルには以下の7つがあります。

種類 概要
起点 最初のチャネルに貢献度が100%割り振られる。
終点 最後のチャネルに貢献度が100%割り振られる。
最後の間接クリック 接点のタイプがクリックのチャネルの中で最後のチャネルに貢献度が100%割り振られる。(最後がダイレクト トラフィックでその前がオーガニック検索の場合、ダイレクト トラフィックはクリックではないためオーガニック検索が評価される)
AdWords広告のラストクリック 最後にクリックしたAdWords広告に貢献度が100%割り振られる。
接点ベース 最初と最後のチャネルに貢献度が40%割り振られ、残り20%は途中のチャネルに均等に割り振られる。
線形 コンバージョン経路の各チャネルに貢献度が均等に割り振られる。
減衰 コンバージョン達成に時間的に近いチャネルほど貢献度が高く割り振られる。

いろいろモデルがあり、どのモデルを採用すればよいか判断が難しいかと思います。完全に私の主観ですが各モデルをこういう時に利用すれば良いのではないかという方向性を簡単に書いてみます。

起点モデル

このモデルを利用することで新規顧客(見込み顧客)にリーチできているチャネルやキャンペーンを分析することができます。もし、サイトで新しい層にリーチを広げたい場合はこのモデルを使うと良いでしょう。

終点モデル

このモデルを利用することでクロージングしているチャネルやキャンペーンを分析することができます。もし、既にある程度ショップの知名度があり、セールスにつなげるためのパイプラインを持っているのであれば、このモデルを使って効率の良いチャネルに集中的に予算を投入すると良いでしょう。

接点モデル

このモデルは顧客の購買サイクルに影響する全てのチャネルを分析しつつも、セールスファネルの中間(ナーチャリングなど)よりもインパクトの大きいトップとボトムに重点を分析することができます。エンド・ツー・エンドのパフォーマンスを重視したい場合に利用すると良いでしょう。

線形モデル

このモデルは各チャネルの貢献度をまんべんなく確認できるため、過度にチャネルの貢献度を低く見積り過ぎてしまうことを防ぐことができます。起点や終点などを重視していると意図せずに過小評価しているチャネルがあるかもしれません。このモデルを使って見落としがないかどうか確認すると良いでしょう。

減衰モデル

このモデルはコンバージョンに近いチャネルに比重を置くことができるため、ユーザーのモチベーションを高めているチャネルを分析する用途に向いています。例えば十分にトラフィックは集められているのに見込み顧客⇒有望見込み顧客⇒顧客へとスムーズに転換出来ていない(販売サイクルが長引いている)場合や、質の高いクオリティのトラフィック(有望見込み顧客)は集められているのにコンバージョンしない場合に利用して分析すると良いでしょう。

各モデルについて簡単に書いてみましたが、恒久的にどれか一つのモデルを採用するというよりも、その時その時に合わせて1つまたは複数のモデルを取り入れて分析する方が良いのではないかと思います。

最後に

普段、A/Bテストやヒートマップによる解析、ブログを使ったSEO対策など様々な施策を行われているかと思います。しかし、以下のようなことになっているのであれば、まずはデータをしっかり分析してユーザーを理解すべきではないでしょうか。

  • ボタンの色や文言、メインビジュアルのA/Bテストをやって他にやることが無くなってしまった
  • ヒートマップツールでよく見られている箇所は分かったけど結局何をして良いのか分からない
  • 取りあえず他のサイトの真似をして記事を量産している

また、いろいろアイデアはあるが効果を具体的な数値で示せないためお客様との話が上手く進まないということもあるでしょう。そのような場合は今回のeコマーストラッキングを利用して金額ベースで効果を算出してみると良いでしょう。正確ではないにしても、数値があればお客様も動きやすいはずです。

本記事が何かのお役に立てれば幸いです。