メインコンテンツへスキップ
見出し画像
Photo byvoice_miwa0401

【第585回】Personalization:Sitemap Builder で Resolver を設定する

    Nobuyuki Watanabe

    前回の記事では、Salesforce Personalization の Google Chrome 拡張機能である Sitemap Builder の Page Types を使用して TrailNest の各ページを、

    • Home

    • Category

    • Product Detail

    • Cart

    • Checkout

    • Order Confirmation

    として認識できるように設定しました。

    Page Type によって、「今表示されているのは何のページなのか」を判定できるようになりましたが、Product Detail を認識できただけでは、まだ、

    • 「どの商品を見ているのか」

    • 「商品の名前は何か」

    • 「価格はいくらなのか」

    といった、具体的なデータまでは取得していません。

    今回は、それを設定していきます。


    Personalization 基礎シリーズ

    Sitemap Builder シリーズ

    Data 360 設定シリーズ

    Personalization 設定シリーズ


    Resolver とは

    Sitemap Builder の Resolver は、Web ページ上から必要な値を取得するための再利用可能な処理です。

    ヘルプドキュメントでは、Resolver を、DOM、URL、Storage、JavaScript Context などから値を取得し、複数の Event や Page Type から 再利用できる小さな関数 として説明しています。

    例えば Product Detail に、

    <main
        id="trailnest-app"
        data-product-id="TN-BP-003"
        data-product-name="Trail Pro 35L"
        data-product-price="139000">

    という HTML があったとします。

    Resolver を使用すると、ここから、

    • Product ID
      → TN-BP-003

    • Product Name
      → Trail Pro 35L

    • Product Price
      → 139000

    のように必要な値だけを取得できます。

    取得した値は、後ほど Product View や Add to Cart などの Event から利用します。

    つまり、今回の Sitemap の流れを簡単にすると、

    • Page Type
      → 「Product Detail が表示されている」と判断

    • Resolver
      → 「表示されている商品は TN-BP-003」と取得

    • Event
      → 「TN-BP-003 が閲覧された」と送信

    という関係になります。

    Sitemap Builder の Resolver は、Salesforce Interactions SDK が持つデータ取得用の Resolver を、画面上から設定できるようにしたものです。

    例えば、CSS Selector (text) を選択すると HTML 要素のテキストを取得し、CSS Selector Attribute を選択すると HTML 要素の指定した属性値を取得します。

    Salesforce Interactions SDK には、これらに対応する fromSelector() や fromSelectorAttribute() などの Resolver が用意されており、Sitemap Builder を使用すると、この処理を JavaScript で一から記述せずに設定できます。


    Resolvers タブを開く

    Sitemap Builder の Resolvers タブを開き、+ Add New Resolver をクリックします。

    画像

    Resolver の作成画面には、主に次の設定があります。
    ※ ここは説明だけにして、下のセクションで実際に手を動かします。

    ① Name

    作成する Resolver の名前です。

    例えば、

    • Product ID

    • Product Name

    • Product Price

    のように、取得する値が分かる名前を設定します。

    後ほど Event から Resolver を選択するため、用途が分かりやすい名前にしておくと便利です。

    ② Kind

    Resolver の作成方法を指定します。

    今回の画面では、

    • Built-in

    • Custom JavaScript

    を選択できます。

    Built-in では、CSS Selector や URL など、Sitemap Builder が用意している方法を使用して値を取得します。

    Custom JavaScript は、Built-in だけでは取得しにくい値を JavaScript で独自に取得したい場合に使用します。

    今回は HTML 上に必要なデータを用意してあるため、基本的に Built-in を使用します。

    ③ Method

    どこから、どのような方法で値を取得するのかを指定します。

    主に次の方法が用意されています。

    • CSS Selector (text)
      CSS Selector に一致する最初の HTML 要素からテキストを取得

    • CSS Selector Attribute
      CSS Selector に一致する最初の HTML 要素から指定した属性を取得

    • CSS Selector (multiple)
      一致する複数の HTML 要素からテキストを取得

    • CSS Selector Attribute (multiple)
      一致する複数の HTML 要素から指定した属性を取得

    • Current URL (href)
      現在表示しているページの URL を取得

    • Meta Tag (name or property)
      HTML の Meta Tag から値を取得

    • Window Path
      window オブジェクト上に存在する値を取得

    などから選択できます。

    例えば、

    CSS Selector (text) は、HTML 要素の表示テキストを取得します。

    <h1 class="product-title">Trail Pro 35L</h1>

    であれば、product-title から、Trail Pro 35L を取得するといった使い方です。

    一方、CSS Selector Attribute は、HTML 要素に設定されている属性の値を取得します。

    例えば、

    <main
        id="trailnest-app"
        data-product-id="TN-BP-003">

    から data-product-id を取得する、といった使い方です。

    今回の TrailNest では data-product-id、data-product-name、data-product-price を用意しているため、この CSS Selector Attribute を多く使用します。

    ④ Output Type

    Built-in Resolver では、取得した値をどのデータ型として扱うか指定します。今回の画面では Text、Number、Boolean、Date から選択できます。

    ※ Custom JavaScript Resolver では Output Type は指定しません。

    例えば

    • Product ID や Product Name は Text、

    • Product Price は Number

    として取得します。

    Tips:HTML から取得した値が文字列であっても、Output Type を Number にすることで数値として扱えるようになります。

    ⑤ Selector

    どの HTML 要素から値を取得するのかを CSS Selector で指定します。

    手入力することもできますが、Pick を使用すると、現在表示している Web ページから対象となる要素を選択できます。

    ⑥ Output

    設定した Resolver が、現在の Web ページから実際にどの値を取得できたかを確認する場所です。

    Resolver を設定するときは、対象となるページをブラウザで開いた状態にしておくと、取得結果を確認しながら設定できます。


    Product ID の Resolver を作成

    それでは、最初の Resolver として Product ID を作成します。

    まず TrailNest で任意の商品を開き、Product Detail を表示しておきます。

    例えば、今回の商品ページには、次のような HTML が存在します。

    <main
        id="trailnest-app"
        data-page-type="product_detail"
        data-product-id="TN-BP-003"
        data-product-name="Trail Pro 35L"
        data-product-price="139000">

    今回取得したいのは、

    data-product-id="TN-BP-003"

    の TN-BP-003 です。

    Add New Resolver をクリックし、次の内容を設定します。

    • Name:Product ID

    • Kind:Built-in

    • Method:CSS Selector Attribute

    • Output Type:Text

    • Selector:#trailnest-app

    • Attribute:data-product-id

    画像

    ここで、

    Selector:#trailnest-app

    は、id="trailnest-app" の HTML 要素を探す という意味です。

    さらに、

    Attribute:data-product-id

    によって、その要素から data-product-id の値を取得します。

    Sitemap Builder では、次のような Resolver が生成されます。

    resolvers.fromSelectorAttribute('#trailnest-app', 'data-product-id')

    fromSelectorAttribute() は、指定した CSS Selector に一致する要素から特定の属性値を取得する Resolver です。

    正常に評価されれば、Output には、

    TN-BP-001

    などが表示されます。

    画像

    これで、現在 Product Detail に表示されている商品の Product ID を取得する Resolver が完成しました。

    Save をクリックして保存します。


    Product Name の Resolver を作成

    続いて Product Name を取得します。

    Product Detail には、

    data-product-name="Trail Pro 35L"

    という属性も用意しています。

    Product ID とほぼ同じ設定で、取得する Attribute だけを変更します。

    • Name:Product Name

    • Kind:Built-in

    • Method:CSS Selector Attribute

    • Output Type:Text

    • Selector:#trailnest-app

    • Attribute:data-product-name

    生成される Resolver は、

    resolvers.fromSelectorAttribute(
        '#trailnest-app',
        'data-product-name'
    )

    となります。

    Output に、Alpine Daypack 18L などと表示されることを確認します。

    画像

    問題がなければ Save をクリックします。


    Product Price の Resolver を作成

    次に Product Price を取得します。

    HTML には、

    data-product-price="139000"

    という値を設定しています。

    設定は次のようにします。

    • Name:Product Price

    • Kind:Built-in

    • Method:CSS Selector Attribute

    • Output Type:Number

    • Selector:#trailnest-app

    • Attribute:data-product-price

    ここで Product ID や Product Name と異なるのが、Output Type を Number にすることです。

    HTML の Attribute から取得した 139000 は、元々文字列として存在していますが、Product Price は後ほど価格として Event に含めるため、Number として扱います。

    生成される Resolver は

    resolvers.fromSelectorAttribute(
        '#trailnest-app',
        'data-product-price'
    )

    となり、Sitemap Builder 側で指定した Output Type に従って数値として扱われます。

    Output に、79000 などと表示されることを確認して Save します。

    画像

    なぜ data-* 属性から取得するのか

    今回、Product ID はページ上に表示されていないものの、Product Name や Product Price は、実際のページに表示されています。

    例えば Product Name なら、画面上の、

    <h1>Trail Pro 35L</h1>

    のような要素を CSS Selector (text) で取得することも可能です。

    それでも今回は、

    data-product-name="Trail Pro 35L"
    data-product-price="139000"

    という Attribute から取得しています。

    理由は、Web ページの見た目とデータ取得をなるべく分離するためです。

    例えばデザイン変更によって、

    • h1.product-title

    が、

    • div.product-header > h2

    に変更されると、表示部分を直接参照していた Resolver は修正が必要 になる可能性があります。

    一方、Sitemap 用に意図して用意した、

    • #trailnest-app

    • data-product-id

    • data-product-name

    • data-product-price

    さえ維持されていれば、画面のレイアウトが変わっても Resolver への影響を抑えられます。

    Selector はできるだけシンプルにし、長い子要素の連鎖や nth-child などに依存せず、ID や一意な Class など安定した情報を利用することが推奨されています。


    Custom JavaScript を使用する

    ここまでの商品情報は、HTML の data-* 属性から値を取得できるため Built-in Resolver を使用しました。

    一方、今回の TrailNest では、

    • 固定値を返したい

    • Form に入力された値を取得したい

    • Local Storage に保存された Order 情報を取得したい

    といったケースもあります。

    このような場合は Custom JavaScript Resolver を使用します。

    Custom JavaScript Resolver では、最終的に値を返す 関数 を設定します。

    例えば、以下のような形です。

    () => 1

    ※ この Resolver が評価されたら、常に 1 を返すの意味です。

    Salesforce Interactions SDK の Resolver 自体も、値そのもの(例:1)ではダメで、あとから評価できる Function を返す仕組み になっています。


    Product Quantity の Resolver を作成

    Add to Cart では、商品 ID や価格だけでなく Quantity も必要になります。

    今回の TrailNest では Add to Cart を 1 回クリックしたときに追加する数量を常に 1 とするため、固定値を返す Resolver を作成します。

    設定は次の通りです。

    • Name:Product Quantity

    • Kind:Custom JavaScript

    Custom JavaScript には次を入力します。

    () => 1

    Output に、「1」 と表示されることを確認して保存します。

    画像

    非常に単純ですが、このように固定値も Resolver として定義しておくことで、後ほど Add to Cart Event から再利用できます。


    Checkout Email の Resolver を作成

    続いて、Checkout ページへ移動します。

    今回の TrailNest では、Checkout で Email Address を入力します。

    HTML には、

    <input
        id="email"
        name="email"
        type="email"
        required>

    が存在します。

    入力された Email Address を取得する Resolver を作成します。

    • Name:Checkout Email

    • Kind:Custom JavaScript

    Custom JavaScript には次を設定します。

    () => (document.querySelector('#email')?.value || '').trim()

    これで Resolver を評価すると、入力した Email Address が Output に表示されます。

    画像

    この Resolver は、後ほど Contact Point Email を作成するときに使用します。


    Checkout Customer ID の Resolver を作成

    今回の TrailNest では、より実際の EC サイトに近づけるために Customer ID も入力するようにしています。

    ※ 本来はログインの手順を踏みますが、今回は入力させるだけです。

    HTML には、

    <input
        id="customerId"
        name="customerId"
        type="text"
        required>

    があります。

    Customer ID は特定の書式には固定していない ため、空欄でなければ任意の ID を入力できます。

    例えば、

    • CUST-000001

    • TEST-001

    • 123456

    などです。

    Resolver は次の内容で作成します。

    • Name:Checkout Customer ID

    • Kind:Custom JavaScript

    () => (document.querySelector('#customerId')?.value || '').trim()

    入力した Customer ID が Output に表示されることを確認します。

    画像

    この値は後ほど Party Identification に使用し、匿名ユーザーの deviceId と既知顧客の Customer ID を関連付けるために利用します。


    Order ID の Resolver を作成

    次に Purchase Event で使用する Order 情報も Resolver として用意します。

    TrailNest では、Place Order を実行すると Order 情報を Local Storage の、

    trailnest_last_order

    に保存します。

    その中には、

    {
        orderId: "TN-...",
        customer: {...},
        items: [...],
        total: ...
    }

    といった情報が含まれています。

    Order ID を取得する Resolver を作成します。

    • Name:Order ID

    • Kind:Custom JavaScript

    () => {
      try {
        const order =
          JSON.parse(
            localStorage.getItem('trailnest_last_order')
          );
    
        return order?.orderId || '';
      } catch (e) {
        return '';
      }
    }

    Order Confirmation ページで評価すると「TN-xxxxxxxxxxxxx」のような Order ID が取得できます。

    画像

    今回 Local Storage を使用するのは、TrailNest が簡易的なデモサイトであり、Checkout で作成した注文情報を Order Confirmation ページへ引き継ぐためです。Salesforce Personalization の実装で Local Storage の利用が必須という意味ではありません。


    Order Total の Resolver を作成

    同じ Order 情報から注文金額も取得します。

    • Name:Order Total

    • Kind:Custom JavaScript

    () => {
      try {
        const order =
          JSON.parse(
            localStorage.getItem('trailnest_last_order')
          );
    
        return Number(order?.total || 0);
      } catch (e) {
        return 0;
      }
    }

    例えば、「188000」のような注文合計金額が取得できます。

    画像

    この値は Purchase Event の Total Value に使用します。


    Order Item 用の Resolver を作成

    最後に、Purchase Event で購入商品の明細を取得するための Resolver も作成します。

    今回の TrailNest では、Order Confirmation に表示される各商品を、次のような HTML 要素として出力しています。

    <div
        class="checkout-summary-item"
        data-product-id="TN-BP-003"
        data-quantity="1"
        data-price="79000">

    画面上の見た目はこれまでと同じですが、Sitemap Builder から商品明細を取得できるよう、

    • data-product-id

    • data-quantity

    • data-price

    を持たせています。

    後ほど Purchase Event の Line Items Selector に、

    • .checkout-summary-item

    を指定します。

    すると Sitemap Builder は、一致したそれぞれの商品要素を $item として Resolver に渡します。

    例えば、商品が 3 件ある場合は、

    1 件目の .checkout-summary-item
    → $item

    2 件目の .checkout-summary-item
    → $item

    3 件目の .checkout-summary-item
    → $item

    という形で、Resolver が商品ごとに評価されます。

    そこで、この $item から Product ID、Quantity、Price を取得する 3 つの Resolver を作成します。

    ① Order Item Product ID

    まず、購入商品の Product ID を取得します。

    • Name:Order Item Product ID

    • Kind:Custom JavaScript

    Custom JavaScript には、次を設定します。

    ($item) => $item.attr('data-product-id') || ''

    「$item.dataset.productId」は、

    • data-product-id="TN-BP-003"

    の値を取得します。

    ② Order Item Quantity

    続いて、購入数量を取得します。

    • Name:Order Item Quantity

    • Kind:Custom JavaScript

    ($item) => Number($item.attr('data-quantity') || 0)

    data-quantity の値を Number として取得します。

    ③ Order Item Price

    最後に、商品の単価を取得します。

    • Name:Order Item Price

    • Kind:Custom JavaScript

    ($item) => Number($item.attr('data-price') || 0)

    data-price の値を Number として取得します。

    ※ ちなみに、$item は Purchase Event の Line Items Mapping から渡されるため、Resolver 単体では実際の値を Preview できません。

    画像

    これで Purchase Event では、

    Line Items Selector
    → .checkout-summary-item

    Catalog Object ID
    → Order Item Product ID

    Quantity
    → Order Item Quantity

    Price
    → Order Item Price

    という形で、購入した商品を 1 件ずつ Line Item として取得できるようになります。

    なお、今回の TrailNest は検証用サイトのため、Sitemap Builder から取得しやすいように Order Confirmation の HTML に data-* 属性を追加していますが、実際の Web サイトでは、Salesforce Personalization のためだけに HTML を変更できない場合もあります。

    その場合は、既存の DOM、dataLayer、JavaScript の state、Local Storage、Commerce 側の注文情報など、サイト上ですでに利用できるデータから Line Items を構成する方法を検討します。


    今回作成した Resolver

    ここまでで、今回の TrailNest で必要となる基本的な Resolver を用意できました。

    商品情報

    • Product ID

    • Product Name

    • Product Price

    • Product Quantity

    Profile 情報

    • Checkout Email

    • Checkout Customer ID

    Order 情報

    • Order ID

    • Order Total

    Order Item 情報

    • Order Item Product ID

    • Order Item Quantity

    • Order Item Price

    商品ページの data-* 属性から取得できる値には Built-in Resolver を使用し、Form や Local Storage などから取得する値には Custom JavaScript Resolver を使用 しました。

    つまり、

    DOM の Attribute
    → Built-in Resolver

    Form の入力値
    → Custom JavaScript Resolver

    Local Storage の Order
    → Custom JavaScript Resolver

    という使い分けです。


    いかがでしたでしょうか。

    次回は Profile Attributes を使用します。

    今回取得した、

    • Checkout Email

    • Checkout Customer ID

    を利用して、

    Email Address
    → Contact Point Email

    Customer ID
    → Party Identification

    として Profile Event に含める方法を確認します。

    これによって、匿名状態で取得してきた Web 行動を、後ほど既知顧客へ関連付けるための準備を進めます。

    今回は以上です。


    次の記事はこちら

    前回の記事はこちら

    私の note のトップページはこちら

     
     
     
    Salesforce Marketing Cloud、Agentforce、Data Cloud、Salesforce 認定資格に関する実践的な情報を発信しています。これらの記事が、皆さまの学習や日々の業務に少しでもお役に立てば幸いです。