建立 Google Tag Manager 自訂像素

您可以將 Google Tag Manager (GTM) 當作自訂像素,用來管理第三方像素。

準備好測試 GTM 自訂像素時,請使用 Shopify Pixel Helper,確認您想追蹤的所有事件已正確加入沙箱且沒有錯誤。

您也可以使用 Google Tag Assistant 頁面擴充功能,測試頁面上載入了哪些 Google 標籤。不過,Google Tag Assistant 的 Troubleshoot tag 功能與自訂像素不相容,無法偵測自訂像素中的任何 Google 標籤,或由 GTM 載入的其他像素。

準備建立自訂像素

在使用 Google Tag Manager 建立自訂像素之前,請先閱讀以下資訊,以確保您瞭解如何設定像素:

建立 Google Tag Manager 自訂像素

您可以建立 Google Tag Manager 自訂像素來管理第三方像素。

步驟:

  1. 開啟您的 Google Tag Manager 帳戶,並選取要設定自訂像素的帳戶。
  2. 按一下 Admin,然後按一下 Install Google Tag Manager,以開啟安裝程式碼。
  3. 複製屬於頁面 head 區段的程式碼區塊。
  4. 從程式碼區塊移除 HTML 標籤。例如,<script></script>
  5. 將其餘程式碼插入新的 Shopify Custom Pixel
  6. Subscribe to customer events and push to GTM’s dataLayer.
  7. 若要檢視程式碼應如何顯示,請參考 example Google Tag Manager custom pixel
  8. Configure Google Tag Manager to accept events from your Custom Pixel.
  9. 選用:如果您的 checkout.liquid 檔案中已有 dataLayer.push(event) 呼叫,則 replace it with analytics.publish()

訂閱顧客事件,並推送至 GTM 的資料層

您可以在自訂像素程式碼中使用 GTM 的 dataLayer 訂閱顧客事件。

系統預設提供一組可供訂閱的 standard events。不過,如果您想追蹤不屬於這些標準事件的顧客事件,您可以 publish your own custom events from Liquid template files

以下示範如何訂閱標準事件「product_viewed」,此事件代表有人檢視商品。當事件觸發時,會將事件推送到 dataLayer

analytics.subscribe("product_viewed", (event) => {
  window.dataLayer.push({
    event: "product_viewed",
    product_title: event.data?.productVariant?.title,
  });
});

在此範例中,會在事件承載資料中傳遞產品名稱。您可以使用 Google Tag Manager variable,從事件承載資料擷取產品名稱,並在您選用的標籤中使用。

Google Tag Manager 自訂像素範例

以下範例是精簡版的 Google Tag Manager 自訂像素,示範如何將資料傳送到 Google Tag Manager。若要將更多事件推送到您的 dataLayer,您可以訂閱更多標準事件與自訂事件。

// Define dataLayer and the gtag function.
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}

//Initialize GTM tag
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer', 'GTM-XXXXXXX');

//Google Consent Mode v2
gtag('consent', 'update', {
  'ad_storage': 'granted',
  'analytics_storage': 'granted',
  'ad_user_data': 'granted',
  'ad_personalization': 'granted',
});

//subscribe to events
analytics.subscribe("checkout_completed", (event) => {
  window.dataLayer.push({
    event: "checkout_completed",
    timestamp: event.timestamp,
    id: event.id,
    token: event.data?.checkout?.token,
    url: event.context.document.location.href,
    client_id: event.clientId,
    email: event.data?.checkout?.email,
    phone: event.data?.checkout?.phone,
    first_name: event.data?.checkout?.shippingAddress?.firstName,
    last_name: event.data?.checkout?.shippingAddress?.lastName,
    address1: event.data?.checkout?.shippingAddress?.address1,
    address2: event.data?.checkout?.shippingAddress?.address2,
    city: event.data?.checkout?.shippingAddress?.city,
    country: event.data?.checkout?.shippingAddress?.country,
    countryCode: event.data?.checkout?.shippingAddress?.countryCode,
    province: event.data?.checkout?.shippingAddress?.province,
    provinceCode: event.data?.checkout?.shippingAddress?.provinceCode,
    zip: event.data?.checkout?.shippingAddress?.zip,
    orderId: event.data?.checkout?.order?.id,
    currency: event.data?.checkout?.currencyCode,
    subtotal: event.data?.checkout?.subtotalPrice?.amount,
    shipping: event.data?.checkout?.shippingLine?.price?.amount,
    value: event.data?.checkout?.totalPrice?.amount,
    tax: event.data?.checkout?.totalTax?.amount,
  });
});

analytics.subscribe("payment_info_submitted", (event) => {
  window.dataLayer.push({
    event: "payment_info_submitted",
    timestamp: event.timestamp,
    id: event.id,
    token: event.data?.checkout?.token,
    url: event.context.document.location.href,
    client_id: event.clientId,
    email: event.data?.checkout?.email,
    phone: event.data?.checkout?.phone,
    first_name: event.data?.checkout?.shippingAddress?.firstName,
    last_name: event.data?.checkout?.shippingAddress?.lastName,
    address1: event.data?.checkout?.shippingAddress?.address1,
    address2: event.data?.checkout?.shippingAddress?.address2,
    city: event.data?.checkout?.shippingAddress?.city,
    country: event.data?.checkout?.shippingAddress?.country,
    countryCode: event.data?.checkout?.shippingAddress?.countryCode,
    province: event.data?.checkout?.shippingAddress?.province,
    provinceCode: event.data?.checkout?.shippingAddress?.provinceCode,
    zip: event.data?.checkout?.shippingAddress?.zip,
    orderId: event.data?.checkout?.order?.id,
    currency: event.data?.checkout?.currencyCode,
    subtotal: event.data?.checkout?.subtotalPrice?.amount,
    shipping: event.data?.checkout?.shippingLine?.price?.amount,
    value: event.data?.checkout?.totalPrice?.amount,
    tax: event.data?.checkout?.totalTax?.amount,
  });
});

analytics.subscribe("checkout_shipping_info_submitted", (event) => {
  window.dataLayer.push({
    event: "checkout_shipping_info_submitted",
    timestamp: event.timestamp,
    id: event.id,
    token: event.data?.checkout?.token,
    url: event.context.document.location.href,
    client_id: event.clientId,
    email: event.data?.checkout?.email,
    phone: event.data?.checkout?.phone,
    first_name: event.data?.checkout?.shippingAddress?.firstName,
    last_name: event.data?.checkout?.shippingAddress?.lastName,
    address1: event.data?.checkout?.shippingAddress?.address1,
    address2: event.data?.checkout?.shippingAddress?.address2,
    city: event.data?.checkout?.shippingAddress?.city,
    country: event.data?.checkout?.shippingAddress?.country,
    countryCode: event.data?.checkout?.shippingAddress?.countryCode,
    province: event.data?.checkout?.shippingAddress?.province,
    provinceCode: event.data?.checkout?.shippingAddress?.provinceCode,
    zip: event.data?.checkout?.shippingAddress?.zip,
    orderId: event.data?.checkout?.order?.id,
    currency: event.data?.checkout?.currencyCode,
    subtotal: event.data?.checkout?.subtotalPrice?.amount,
    shipping: event.data?.checkout?.shippingLine?.price?.amount,
    value: event.data?.checkout?.totalPrice?.amount,
    tax: event.data?.checkout?.totalTax?.amount,
  });
});

analytics.subscribe("checkout_address_info_submitted", (event) => {
  window.dataLayer.push({
    event: "checkout_address_info_submitted",
    timestamp: event.timestamp,
    id: event.id,
    token: event.data?.checkout?.token,
    url: event.context.document.location.href,
    client_id: event.clientId,
    email: event.data?.checkout?.email,
    phone: event.data?.checkout?.phone,
    first_name: event.data?.checkout?.shippingAddress?.firstName,
    last_name: event.data?.checkout?.shippingAddress?.lastName,
    address1: event.data?.checkout?.shippingAddress?.address1,
    address2: event.data?.checkout?.shippingAddress?.address2,
    city: event.data?.checkout?.shippingAddress?.city,
    country: event.data?.checkout?.shippingAddress?.country,
    countryCode: event.data?.checkout?.shippingAddress?.countryCode,
    province: event.data?.checkout?.shippingAddress?.province,
    provinceCode: event.data?.checkout?.shippingAddress?.provinceCode,
    zip: event.data?.checkout?.shippingAddress?.zip,
    orderId: event.data?.checkout?.order?.id,
    currency: event.data?.checkout?.currencyCode,
    subtotal: event.data?.checkout?.subtotalPrice?.amount,
    shipping: event.data?.checkout?.shippingLine?.price?.amount,
    value: event.data?.checkout?.totalPrice?.amount,
    tax: event.data?.checkout?.totalTax?.amount,
  });
});

analytics.subscribe("checkout_contact_info_submitted", (event) => {
  window.dataLayer.push({
    event: "checkout_contact_info_submitted",
    timestamp: event.timestamp,
    id: event.id,
    token: event.data?.checkout?.token,
    url: event.context.document.location.href,
    client_id: event.clientId,
    email: event.data?.checkout?.email,
    phone: event.data?.checkout?.phone,
    first_name: event.data?.checkout?.shippingAddress?.firstName,
    last_name: event.data?.checkout?.shippingAddress?.lastName,
    address1: event.data?.checkout?.shippingAddress?.address1,
    address2: event.data?.checkout?.shippingAddress?.address2,
    city: event.data?.checkout?.shippingAddress?.city,
    country: event.data?.checkout?.shippingAddress?.country,
    countryCode: event.data?.checkout?.shippingAddress?.countryCode,
    province: event.data?.checkout?.shippingAddress?.province,
    provinceCode: event.data?.checkout?.shippingAddress?.provinceCode,
    zip: event.data?.checkout?.shippingAddress?.zip,
    orderId: event.data?.checkout?.order?.id,
    currency: event.data?.checkout?.currencyCode,
    subtotal: event.data?.checkout?.subtotalPrice?.amount,
    shipping: event.data?.checkout?.shippingLine?.price?.amount,
    value: event.data?.checkout?.totalPrice?.amount,
    tax: event.data?.checkout?.totalTax?.amount,
  });
});

analytics.subscribe("checkout_started", (event) => {
  window.dataLayer.push({
    event: "checkout_started",
    timestamp: event.timestamp,
    id: event.id,
    token: event.data?.checkout?.token,
    url: event.context.document.location.href,
    client_id: event.clientId,
    email: event.data?.checkout?.email,
    phone: event.data?.checkout?.phone,
    first_name: event.data?.checkout?.shippingAddress?.firstName,
    last_name: event.data?.checkout?.shippingAddress?.lastName,
    address1: event.data?.checkout?.shippingAddress?.address1,
    address2: event.data?.checkout?.shippingAddress?.address2,
    city: event.data?.checkout?.shippingAddress?.city,
    country: event.data?.checkout?.shippingAddress?.country,
    countryCode: event.data?.checkout?.shippingAddress?.countryCode,
    province: event.data?.checkout?.shippingAddress?.province,
    provinceCode: event.data?.checkout?.shippingAddress?.provinceCode,
    zip: event.data?.checkout?.shippingAddress?.zip,
    orderId: event.data?.checkout?.order?.id,
    currency: event.data?.checkout?.currencyCode,
    subtotal: event.data?.checkout?.subtotalPrice?.amount,
    shipping: event.data?.checkout?.shippingLine?.price?.amount,
    value: event.data?.checkout?.totalPrice?.amount,
    tax: event.data?.checkout?.totalTax?.amount,
  });
});

analytics.subscribe("product_added_to_cart", (event) => {
  window.dataLayer.push({
    event: "product_added_to_cart",
    timestamp: event.timestamp,
    id: event.id,
    client_id: event.clientId,
    url: event.context.document.location.href,
    price: event.data?.cartLine?.merchandise?.price?.amount,
    currency: event.data?.cartLine?.merchandise?.id,
    product_title: event.data?.cartLine?.merchandise?.product?.title,
    quantity: event.data?.cartLine?.quantity,
    total_cost: event.data?.cartLine?.cost?.totalAmount?.amount,
  });
});

analytics.subscribe("cart_viewed", (event) => {
  window.dataLayer.push({
    event: "cart_viewed",
    timestamp: event.timestamp,
    id: event.id,
    client_id: event.clientId,
    url: event.context.document.location.href,
    total_cost: event.data?.cart?.cost?.totalAmount?.amount,
    quantity: event.data?.cart?.totalQuantity,
    cart_id: event.data?.cart?.id,
  });
});

analytics.subscribe("page_viewed", (event) => {
  window.dataLayer.push({
    event: "page_viewed",
    timestamp: event.timestamp,
    id: event.id,
    client_id: event.clientId,
    url: event.context.document.location.href,
    page_title: event.context.document.title,
  });
});

analytics.subscribe("product_viewed", (event) => {
  window.dataLayer.push({
    event: "product_viewed",
    timestamp: event.timestamp,
    id: event.id,
    client_id: event.clientId,
    url: event.context.document.location.href,
    product_id: event.data?.productVariant?.product?.id,
    product_title: event.data?.productVariant?.title,
    product_sku: event.data?.productVariant?.sku,
  });
});

analytics.subscribe("search_submitted", (event) => {
  window.dataLayer.push({
    event: "search_submitted",
    timestamp: event.timestamp,
    id: event.id,
    client_id: event.clientId,
    url: event.context.document.location.href,
    query: event.data?.searchResult?.query,
  });
});

analytics.subscribe("collection_viewed", (event) => {
  window.dataLayer.push({
    event: "collection_viewed",
    timestamp: event.timestamp,
    id: event.id,
    client_id: event.clientId,
    url: event.context.document.location.href,
    collection_id: event.data?.collection?.id,
    collection_title: event.data?.collection?.title,
  });
});

設定 Google Tag Manager 以接受自訂像素傳送的事件

建立自訂像素後,您需要設定 Google Tag Manager 以接受自訂像素傳送的事件。為此,您需要在 Google Tag Manager 中建立標籤、觸發條件,以及 dataLayer 變數。

下表列出部分標準顧客事件及其在 Google Tag Manager 中的對應事件:

可搭配像素使用的 Shopify 標準顧客事件清單、其在 Google Tag Manager 中對應的顧客事件,以及觸發事件所需的觸發條件。
Shopify 事件觸發條件GTM 事件
payment_info_submitted提交付款資訊add_payment_info
checkout_address_info_submitted提交運送資訊add_shipping_info
product_added_to_cart將品項加入購物車add_to_cart
checkout_started開始結帳begin_checkout
checkout_completed完成結帳purchase
product_removed_from_cart從購物車移除品項remove_from_cart
cart_viewed檢視購物車view_cart
product_viewed檢視商品詳情頁面view_item
collection_viewed檢視品項清單view_item_list

為了讓系統處理您的自訂像素 dataLayer 事件,GTM 標籤的事件參數必須符合 expected naming conventions

以下是部分自訂像素 dataLayer 事件屬性及其在 Google Analytics 4 (GA4) 中對應事件參數的範例:

採用 GA4 命名慣例的自訂像素 dataLayer 事件清單
自訂像素 dataLayer 事件GA4 事件參數
event.data?.checkout?.currencyCodecurrency
event.data?.checkout?.totalPrice?.amountvalue
event.data?.checkout?.order?.idtransaction_id
event.data?.checkout?.discountAllocationscoupon
event.data?.checkout?.shippingLine?.price?.amountshipping
event.data?.checkout?.totalTaxtax
event.data?.checkout?.lineItemsitems

以下是使用 checkout_completed 事件的範例:

analytics.subscribe("checkout_completed", (event) => {
  window.dataLayer.push({
    event: "checkout_completed",
    orderId: event.data?.checkout?.order?.id,
    currency: event.data?.checkout?.currencyCode,
    price: event.data.checkout.totalPrice.amount,
    shippingLine: event.data.checkout.shippingLine.price.amount,
    totalTax: event.data.checkout.totalTax,
  });
});

Google Tag Manager 的觸發條件是自訂事件類型,事件名稱為 checkout_completed。觸發條件中的 Event name 欄位必須與您的自訂像素中的 event 鍵相符。

orderIdcurrency 是您在 Google Tag Manager 中用來擷取事件資料的變數。您可以將它們對應到 Google Tag Manager 中的 dataLayer 變數。每個事件變數都需要各自的 dataLayer 變數。將觸發條件設定為在所有自訂事件上觸發。

建立一個使用您剛剛建立的觸發條件的標籤。在事件參數中,加入您要擷取的變數。以上述範例而言,orderIdcurrencypriceshippingLinetotalTax 會設定為 dataLayer 變數。每次標籤觸發時,會連同事件一併擷取這些 dataLayer 變數。

請注意,必須先在 Google Tag Manager 設定至少一個標籤與觸發條件,才會進行資料傳輸。

以 analytics.publish() 取代舊的 dataLayer.push(event) 呼叫

如果您先前已設定 Google Tag Manager,則必須將 dataLayer.push 呼叫改成 Shopify.analytics.publish() 呼叫。您可以在 theme.liquid 檔案中,以及佈景主題編輯器的 Layout 區段找到您的 dataLayer.push 呼叫。

您也必須替換 checkout.liquid 中的 dataLayer.push 呼叫。不過,由於 checkout.liquid 與 Shopify Extensions 不相容,您需要使用 UI 擴充功能將資料推送到網頁像素。

以下是使用 dataLayer 在 theme.liquid 檔案中追蹤自訂電子郵件註冊事件的簡化範例:

<script>
  dataLayer.push({ event: 'email_signup', email: customer.email });
</script>

Shopify 的對應作法如下,會將資料推送至您的自訂像素:

<script>
  Shopify.analytics.publish('email_signup', {email: customer.email });
</script>

接著,請在您的 自訂像素程式碼 中加入類似以下內容:

analytics.subscribe("email_signup", (event) => {
  window.dataLayer.push({
   'event': 'email_signup',
   'email': event.customData.email,
  });
});

取代舊的 dataLayer.push(data)

Google Tag Manager 具備一項功能,允許您在每個事件上推送具狀態的 dataLayer 物件。雖然 Shopify 的像素沙箱不包含等同的功能,但您可以建立自己的資料物件並傳入自訂事件,以達成相同效果。

例如,請先在發布任何自訂事件之前定義「customData」物件:

<script>
  const customData = {email: customer.email}
</script>

之後,每當您要包含自訂資料時,都將它傳入您的發布方法:

<script>
  Shopify.analytics.publish('email_signup', customData);
</script>

設定 Google Analytics 4 的提示

當您使用 Google Tag Manager 作為自訂像素時,請參考以下設定 Google Analytics 4 (GA4) 的提示。

更乾淨的頁面網址

在沙箱中執行 GA4 時,您可能會注意到頁面網址包含它所執行的沙箱相關資訊。若您想移除這些網址中的沙箱資訊,可以 turn off GA4’s automatic pages tracking,改用標準的 page_viewed 事件自行實作。

analytics.subscribe('page_viewed', (event) => {
  window.dataLayer.push({
   'event': 'page_viewed',
   'page_location': event.context.window.location.href,
   'page_title': event.context.document.title,
  });
});

將您自己的事件發布到 dataLayer 之後,您可以建立一個在 page_viewed 事件上觸發的 GA4 page_view 標籤。通常您可以使用 Google Analytics: GA4 Event 標籤類型,並將 Event Name 設為 page_view。設定好標籤類型與事件名稱後,請新增 page_location 參數,並將其值設為您從自訂像素傳入 dataLayer 的相同值。

加強型衡量

在 Shopify 的像素沙箱中載入 GA4 時,原本會自動推斷的部分事件需要手動設定。舉例來說,外部連結點擊屬於 GA4 的加強型衡量設定,使用自訂像素時,基於安全性考量無法自動觸發。不過,您可以自行將 GA4 的 enhanced measurement events 以自訂事件方式實作。

以下程式碼提供一個追蹤外部連結點擊的簡化範例:

<script>
  function detectOutboundLink() {
    // add your logic for determining if a link click is outbound

    // if the link click is outbound then publish it
    if (isOutboundLink) {
      Shopify.analytics.publish('outbound_link', { link_url: link_url });
    }
  }
</script>

最後,在 GTM 中建立一個 GA4 標籤,將連結點擊送至 GA4,並確保事件名稱為 click,以符合 GA4’s enhanced event naming

上述做法同樣適用於所有 Google 的加強型衡量指標。

測試與除錯您的自訂像素

準備好測試 GTM 自訂像素時,請使用 Shopify Pixel Helper,確認您想追蹤的所有事件已正確加入沙箱且沒有錯誤。

您也可以使用 Google Tag Assistant 頁面擴充功能,測試頁面上載入了哪些 Google 標籤。不過,Google Tag Assistant 的 Troubleshoot tag 功能與自訂像素不相容,無法偵測自訂像素中的任何 Google 標籤,或由 GTM 載入的其他像素。