Adobe Client Data Layer連携
ページの情報やユーザー操作を、いわゆるタグマネージャー(Adobe Launch、GTM等)に橋渡しするためのデータレイヤーとして、Adobe Client Data Layer(公式npmパッケージ、以下ACDL)を採用しています。
初期化
src/layouts/Base.astroの<head>内、他のどのスクリプトよりも先に初期化します。
<script is:inline define:vars={{ pageContext }}>
window.adobeDataLayer = window.adobeDataLayer || [];
window.adobeDataLayer.push({ page: pageContext });
</script>
<script>
import '@adobe/adobe-client-data-layer/dist/adobe-client-data-layer.min.js';
</script>
window.adobeDataLayerを配列として先に初期化し、そこにpageコンテキストをpushしてから、ACDL本体を読み込みます。ACDL本体は既存の配列を検知して、push/getState/addEventListenerを持つ本来のオブジェクトに拡張します(公式推奨の初期化パターンです)。
pageContextはページのfrontmatter(title/pageType)から供給されます。eventキーを持たないpushは「状態」としてマージされ、履歴には残りません。
window.adobeDataLayer.push({
page: {
pageName: string,
pageType: string, // "top" | "product" | "cart" | ... (frontmatterのpageTypeと同じenum)
locale: string, // 多言語対応時のみ
},
});
イベントのpush: 2つのパターン
判断基準は「横断的な状態変化(ページ/カート/会員セッション)か、Blockローカルな操作か」です。
パターンB: Block直接push(推奨、まずはこちらを検討)
モーダルの開閉・タブ切り替え・アコーディオンのトグルなど、個々のBlock内で完結する操作は、Blockの<script>から直接pushします。
// src/lib/acdl.ts
export function pushEvent(eventName: string, payload: Record<string, unknown> = {}): void {
window.adobeDataLayer.push({ event: eventName, ...payload });
}
<!-- 例: src/blocks/accordion/index.astro -->
<script>
import { pushEvent } from '../../lib/acdl';
document.querySelectorAll('.accordion__item').forEach((item) => {
item.addEventListener('toggle', () => {
const label = item.querySelector('.accordion__title')?.textContent ?? '';
pushEvent('accordion_toggle', { blockName: 'accordion', label, state: item.open ? 'open' : 'closed' });
});
});
</script>
イベント名の強制フォーマットはありませんが、<blockname>_<action>(例: accordion_toggle)を推奨します。新しいBlockを追加するたびに中央側を修正する必要がなく、「ディレクトリを1つ足すだけ」というBlockの設計思想と整合します。
パターンA: 中央集権ブリッジ(横断的な状態変化)
カート状態の変化、会員のログイン/ログアウト、ページ到達によるライフサイクルイベント(view_item/begin_checkout/purchase)など、特定のBlockに閉じない変化は、中央の1箇所にまとめます。commerceモジュールのacdl-bridge.tsとmemberモジュールのacdl-bridge.tsがいずれもこの実例です。
cart.ts (状態管理。ベンダー非依存)
↓ window.dispatchEvent(new CustomEvent('cart:change', ...))
acdl-bridge.ts (ACDL特化のマッピング層)
↓ window.adobeDataLayer.push({ event: 'add_to_cart', ... })
adobe-client-data-layer
状態管理モジュール(cart.tsやmember.ts)自身はACDLの存在を一切知りません。汎用イベント(cart:change、member:login等)を発火するだけです。ツールを乗り換える場合も、書き換えが必要なのはブリッジ層だけで済みます。
中央集権ブリッジのモジュールは、そのイベントが発生しうる全ページで明示的にimportする必要があります。静的サイトはページ遷移のたびに全JSが読み込み直されるため、共通レイアウトから自動で読み込まれるわけではありません(memberモジュールのacdl-bridge.tsは例外的に、member.enabled時に全ページへ差し込まれるMemberOverlay.astroから読み込まれているため、実質的にどのページでもimport漏れが起きません)。
ECライフサイクルイベント(commerceモジュール、page/イベント本体)
commerceモジュールを使うサイトでは、以下のイベントが発火します。
view_item— PDPページ読み込み時。PDPページの初期化スクリプトが直接pushadd_to_cart— カートに追加/数量増加時。commerceのacdl-bridge.tsがpushremove_from_cart— カートから削除/数量減少時。commerceのacdl-bridge.tsがpushbegin_checkout— チェックアウトページ(/commerce/cart/checkout)読み込み時。同ページの初期化スクリプトが直接pushpurchase— 注文完了ページ(/commerce/order)読み込み時。同ページの初期化スクリプトが直接push
add_to_cartのペイロード例です。
window.adobeDataLayer.push({
event: 'add_to_cart',
product: { sku, name, categories, price, currency, quantity },
});
purchaseのペイロード例です。
window.adobeDataLayer.push({
event: 'purchase',
order: { orderId, currency, total, items: [{ sku, name, price, quantity }] },
});
詳しくはcommerceモジュールを参照してください。
user名前空間(memberモジュール)
member機能(site.config.tsのmember.enabled)を使うサイトでは、ログイン中の会員情報をuser名前空間としてpushします。担当はsrc/modules/member/lib/acdl-bridge.tsで、member.tsが発火するmember:login/member:logout(ベンダー非依存のCustomEvent)を購読し、変換します。
- ログイン時 —
window.adobeDataLayer.push({ user: { id: member.id, ...member.attributes } })。会員発行ページで設定した属性(attributes)がそのままuserオブジェクトに展開されます - ログアウト時 —
window.adobeDataLayer.push({ user: null })
pageと同様、eventキーを持たないpushなので「状態」としてマージされ、履歴には残りません。タグマネージャー側からは「現在ログイン中かどうか、ログイン中なら誰か」という状態として参照する使い方を想定しています。
window.adobeDataLayerはページ単位(フルページ遷移で消える)なので、pageコンテキストと同様、ページの読み込み時点で既にログイン中ならuser状態を再pushします。これが無いと、たとえば会員発行ページのクイックログインから別ページへ遷移した直後に、遷移前のページでpushしたuser情報が新しいページのadobeDataLayerに反映されない、という問題が起こります。
memberモジュールのacdl-bridge.tsは、member.enabled時に全ページへ差し込まれるMemberOverlay.astroから読み込まれています。そのため、ログイン/ログアウトが会員発行ページ・ログインページ・オーバーレイ自身のどこで起きても、確実にACDLへ届きます(中央集権ブリッジのimport漏れが構造的に起きないケースです)。会員機能全体の詳しい説明は会員機能(ログインダミーシステム)を参照してください。
マーケティングタグの注入(タグマネージャー本体等)
Adobe Launch/GTM等のタグ本体は、コードを直接編集せずsite.config.tsで設定します。Base.astroが、ACDL初期化の後・他のどのスクリプトより前にこの設定を出力するため、タグマネージャーが読み込まれる時点でwindow.adobeDataLayerが必ず存在する状態が保証されます。
新しいイベントを追加する
- パターンA/Bのどちらかを判定する
- パターンBなら該当Blockの
<script>にpushEvent()を追記、パターンAなら中央のブリッジ層に購読処理を追加(パターンAの場合はimportの配線を忘れないこと) - 実際にpushされることをブラウザの開発者ツール等で確認する
動作確認方法
Playwrightなどでpushを検証する場合は、ACDL本体の読み込み前に「関数push」でリスナー登録を仕込みます(ACDLはtypeof item === 'function'のpushをFCTNアイテムとして認識し、ライブラリ初期化時にdataLayerインスタンスを引数に実行します)。window.adobeDataLayer.push自体を独自関数で上書きする方式は、ライブラリ初期化時にその上書きが失われるため使えません。
await page.addInitScript(() => {
window.adobeDataLayer = window.adobeDataLayer || [];
window.__acdlEvents = [];
window.adobeDataLayer.push((dataLayer) => {
dataLayer.addEventListener('adobeDataLayer:change', (event) => {
window.__acdlEvents.push(event);
});
});
});
将来の拡張
CMPの同意状態は、consentといった新しい名前空間を追加でpushするだけで対応できる設計になっています(既存のpage/user/イベント構造の変更は不要)。現時点ではこのスキーマは未設計です。