GTM MANUAL SETUP GUIDE
======================

For most users, the bundled template (Main Settings → GTM Container ID →
"Download gtm-template.json") is the fastest path: import it in Merge mode
with "Overwrite conflicting tags, triggers, and variables", set the pixel-code
constants, publish, done.

This document covers the manual path — useful if you cannot import the JSON
template (workspace permission errors, locked containers) or you want to
understand exactly what the import does so you can audit the tags before
shipping them.


PREREQUISITES
-------------

In your Meta Business Suite → Events Manager → your Pixel → Settings → Event
Setup, turn OFF the toggle for "Track Events Automatically Without Code".
This plugin handles all event sending; leaving Meta's auto-tracking on will
double-count events on top of the plugin's deduplicated event_id stream.

In your GTM container, pause or delete any auto-created tags that start with
FB_. Since you will be creating your own tags, only those should be active.


STEP 1 — DATA LAYER VARIABLES
-----------------------------

Create the following Data Layer Variables (Variable Type: Data Layer Variable):

* DLV - event_id                       — Data Layer Variable Name: event_id
* DLV - ecommerce                      — Data Layer Variable Name: ecommerce
* DLV - Hashed Email                   — Data Layer Variable Name: user_data.email
* DLV - ecommerce.currency             — Data Layer Variable Name: ecommerce.currency
* DLV - ecommerce.value                — Data Layer Variable Name: ecommerce.value
* DLV - ecommerce.items                — Data Layer Variable Name: ecommerce.items
* DLV - ecommerce.transaction_id       — Data Layer Variable Name: ecommerce.transaction_id
* DLV - ecommerce.item_list_name       — Data Layer Variable Name: ecommerce.item_list_name
* DLV - ecommerce.shipping_method      — Data Layer Variable Name: ecommerce.shipping_method
* DLV - ecommerce.payment_method       — Data Layer Variable Name: ecommerce.payment_method


CONSTANT VARIABLES
------------------

One placeholder per platform — every Meta tag, every TikTok tag, and every
GA4 tag references these, so rotating IDs requires only one edit:

* CONST - Meta Pixel ID          — your Meta Pixel ID (e.g. 1234567890123456)
* CONST - TikTok Pixel Code      — your TikTok Pixel Code from TikTok Events Manager
* CONST - GA4 Measurement ID     — your GA4 Measurement ID (e.g. G-XXXXXXXXXX)


PINTEREST CUSTOM JS VARIABLE
----------------------------

Only needed if you actually use Pinterest. (Meta's modern Pixel template
auto-converts the GA4 ecommerce schema, so a Meta-side CJS is no longer
required.)

* CJS - Pinterest Contents

  function() {
    var ecommerce = {{DLV - ecommerce}};
    if (!ecommerce || !ecommerce.items) return undefined;
    return ecommerce.items.map(function(item) {
      return {
        id: item.id || item.item_id,
        quantity: item.quantity || 1,
        item_price: item.price
      };
    });
  }


STEP 2 — TRIGGERS
-----------------

Create the following triggers using the Custom Event type:

* CE - PageView Meta        — Event name: page_view_meta
* CE - View Item            — Event name: view_item
* CE - Add to Cart          — Event name: add_to_cart
* CE - Begin Checkout       — Event name: begin_checkout
* CE - Purchase             — Event name: purchase
* CE - View Item List       — Event name: view_item_list
* CE - View Cart            — Event name: view_cart
* CE - Select Item          — Event name: select_item
* CE - Add Shipping Info    — Event name: add_shipping_info
* CE - Add Payment Info     — Event name: add_payment_info
* CE - Login                — Event name: login
* CE - RemoveFromCart       — Event name: remove_from_cart

There is no "search" data layer event to trigger on. A store search is
reported straight to Meta, Pinterest and TikTok from the server the
moment someone searches, so there is nothing for GTM to pick up there.

The trigger used for Advanced Matching (mcapi_identity) is covered on
its own in STEP 4 below, since it feeds fields on the Meta Pixel tag
rather than firing a platform event.


STEP 3 — TAGS
-------------

A) META TAGS

Prerequisite: install the "Meta Pixel" template by facebook from the GTM
Community Template Gallery. (The older "Facebook Pixel" template under
facebookarchive is deprecated and will not import.)

For every Meta tag, set these common fields the same way:

* Pixel ID:                  {{CONST - Meta Pixel ID}}
* Event ID:                  {{DLV - event_id}}   (required for dedup)
* Use GA4 Ecommerce data:    enabled              (auto-converts items[] → contents[])
* Consent Granted (GDPR):    enabled
* Send page view:            leave default

The Meta template's "Consent Granted (GDPR)" field is a latch, not a consent
reader: set to false the pixel queues everything until some tag sets it true,
and it never looks at Consent Mode by itself. Leave it enabled and gate the
tag with GTM's own check instead. Open Advanced Settings → Consent Settings →
Additional Consent Checks, choose "Require additional consent for this tag",
and put ad_storage and ad_user_data in the table. A denied visitor then never
fires the tag at all. Set this on every Meta tag below.

Then per tag, only the Event Name and Trigger change:

* Meta - PageView            → standard PageView,         Trigger: CE - PageView Meta
* Meta - ViewContent         → standard ViewContent,      Trigger: CE - View Item
* Meta - AddToCart           → standard AddToCart,        Trigger: CE - Add to Cart
* Meta - InitiateCheckout    → standard InitiateCheckout, Trigger: CE - Begin Checkout
* Meta - Purchase            → standard Purchase,         Trigger: CE - Purchase
* Meta - AddPaymentInfo      → standard AddPaymentInfo,   Trigger: CE - Add Payment Info
* Meta - ViewCategory        → custom event "ViewCategory", Trigger: CE - View Item List
                               (Meta has no standard ViewCategory event)


B) PINTEREST TAGS

Prerequisite: install the "Pinterest Tag" template from the GTM Community
Template Gallery. The Data Layer Variables and CJS - Pinterest Contents from
Step 1 are reused here.

Standard custom-parameter set used by most Pinterest tags:
  event_id      → {{DLV - event_id}}
  value         → {{DLV - ecommerce.value}}
  currency      → {{DLV - ecommerce.currency}}
  contents      → {{CJS - Pinterest Contents}}
  content_ids   → {{CJS - Pinterest Contents}}  (Pinterest extracts ids from the array)

Create the following tags:

* Pinterest - PageView
    Tag ID:           your Pinterest Tag ID
    Hashed Email:     {{DLV - Hashed Email}}
    Event to Fire:    page_visit
    Custom Params:    event_id → {{DLV - event_id}}
    Trigger:          CE - PageView Meta

* Pinterest - ViewContent
    Tag ID:           your Pinterest Tag ID
    Hashed Email:     {{DLV - Hashed Email}}
    Event to Fire:    view_content
    Custom Params:    standard set above
    Trigger:          CE - View Item

* Pinterest - AddToCart
    Event to Fire:    add_to_cart
    Custom Params:    standard set
    Trigger:          CE - Add to Cart

* Pinterest - InitiateCheckout
    Event to Fire:    initiate_checkout
    Custom Params:    standard set
    Trigger:          CE - Begin Checkout

* Pinterest - Purchase
    Event to Fire:    checkout
    Custom Params:    standard set
    Trigger:          CE - Purchase

* Pinterest - ViewCategory
    Event to Fire:    view_category
    Custom Params:
      event_id     → {{DLV - event_id}}
      content_name → {{DLV - ecommerce.item_list_name}}
    Trigger:          CE - View Item List


C) TIKTOK TAGS

Prerequisite: install the "TikTok Pixel" template by tiktok from the GTM
Community Template Gallery.

For every TikTok tag, set these common fields:

* Pixel Code:                {{CONST - TikTok Pixel Code}}
* Event ID:                  {{DLV - event_id}}    (required for dedup)
* Use enhanced ecommerce:    enabled               (auto-converts items[] → contents[])

The TikTok template has no consent field of any kind, so the tag-level check
is the only thing standing between a denied visitor and the pixel. Open
Advanced Settings → Consent Settings → Additional Consent Checks, choose
"Require additional consent for this tag", and put ad_storage and
ad_user_data in the table. Set this on every TikTok tag below.

Event names below are TikTok's standard event roster. TikTok has no
ViewCategory event, so the plugin maps ViewCategory to Pageview server-side
and the template fires Pageview for the View Item List trigger:

* TikTok - Pageview                  → Pageview,            CE - PageView Meta
* TikTok - ViewContent               → ViewContent,         CE - View Item
* TikTok - AddToCart                 → AddToCart,           CE - Add to Cart
* TikTok - InitiateCheckout          → InitiateCheckout,    CE - Begin Checkout
* TikTok - AddPaymentInfo            → AddPaymentInfo,      CE - Add Payment Info
* TikTok - Purchase                  → Purchase,            CE - Purchase
* TikTok - Pageview (View Item List) → Pageview,            CE - View Item List


D) GA4 TAGS

Prerequisite: have your Measurement ID (starts with G-) from your GA4
property. The Data Layer Variables from Step 1 are reused.

First, create the main configuration tag:

* GA4 - Google Tag (Configuration)
    Tag Type:   Google Analytics > Google Tag
    Tag ID:     your GA4 Measurement ID
    Important:  Uncheck "Send a page view event when this configuration loads"
                — we send page_view manually below.
    Trigger:    All Pages

Then create event tags. All GA4 event tags use:
    Tag Type:         Google Analytics > GA4 Event
    Configuration Tag: GA4 - Google Tag (Configuration)

* GA4 - Event - PageView
    Event Name:       page_view
    Trigger:          CE - PageView Meta

* GA4 - Event - ViewItem
    Event Name:       view_item
    Params:           currency, value, items (from DLV)
    Trigger:          CE - View Item

* GA4 - Event - AddToCart
    Event Name:       add_to_cart
    Params:           currency, value, items
    Trigger:          CE - Add to Cart

* GA4 - Event - BeginCheckout
    Event Name:       begin_checkout
    Params:           currency, value, items
    Trigger:          CE - Begin Checkout

* GA4 - Event - Purchase
    Event Name:       purchase
    Params:           transaction_id, currency, value, items
    Trigger:          CE - Purchase

* GA4 - Event - ViewItemList
    Event Name:       view_item_list
    Params:           item_list_name, items
    Trigger:          CE - View Item List

* GA4 - Event - ViewCart
    Event Name:       view_cart
    Params:           currency, value, items
    Trigger:          CE - View Cart

* GA4 - Event - SelectItem
    Event Name:       select_item
    Params:           items
    Trigger:          CE - Select Item

* GA4 - Event - AddShippingInfo
    Event Name:       add_shipping_info
    Params:           currency, value, shipping_tier (= shipping_method), items
    Trigger:          CE - Add Shipping Info

* GA4 - Event - AddPaymentInfo
    Event Name:       add_payment_info
    Params:           currency, value, payment_type (= payment_method), items
    Trigger:          CE - Add Payment Info

* GA4 - Event - Login
    Event Name:       login
    Trigger:          CE - Login
    Note: Meta already gets Login sent straight from the server, so this
    GA4 tag is the only one this event needs in GTM.

* GA4 - Event - RemoveFromCart
    Event Name:       remove_from_cart
    Params:           currency, value, items
    Trigger:          CE - RemoveFromCart


E) GOOGLE ADS TAGS (Enhanced Conversions)

Prerequisite: in Google Ads, go to Goals → Conversions → your Purchase
conversion action → Tag setup → "Install the tag yourself" to get:
  - Conversion ID (format: AW-1234567890)
  - Conversion Label (format: abc123XYZ)

Enable Enhanced Conversions for that conversion action in the Google Ads
UI first (Goals → Conversions → click conversion → Enhanced Conversions
tab → "Turn on enhanced conversions" → "Google tag" method). This is the
Google Ads-side setting that allows the tag we configure below to send
hashed user data.

Step 1 — Two new CONST variables:

* CONST - Google Ads Conversion ID      Value: the number on its own, e.g.
                                        1234567890 for AW-1234567890. The two
                                        fields below want different forms of
                                        it, and the AW- prefix is added where
                                        it is needed rather than stored here.
* CONST - Google Ads Purchase Label     Value: your conversion label

Step 2 — Google Ads Google Tag (fires on All Pages):

Note: modern GTM has folded standalone "Conversion Linker" into the
unified Google Tag. Adding a Google Tag with your Google Ads ID on
All Pages provides identical gclid / gbraid / wbraid capture behavior.

* Google Ads - Google Tag (Conversion Linker)
    Tag Type:        Google Tag
    Tag ID:          AW-{{CONST - Google Ads Conversion ID}}
    Trigger:         All Pages

Auto-captures gclid / gbraid / wbraid from ad-click URLs into the
_gcl_aw first-party cookie. Required for the Purchase Conversion tag
below to attribute conversions correctly.

Step 3 — Google Ads Conversion Tracking tag (fires on CE - Purchase):

* Google Ads - Purchase Conversion
    Tag Type:                   Google Ads Conversion Tracking
    Conversion ID:              {{CONST - Google Ads Conversion ID}}
                                (this field takes the number with no AW-)
    Conversion Label:           {{CONST - Google Ads Purchase Label}}
    Conversion Value:           {{DLV - ecommerce.value}}
    Currency Code:              {{DLV - ecommerce.currency}}
    Order ID:                   {{DLV - ecommerce.transaction_id}}
    Enable Conversion Linker:   ENABLED
    Trigger:                    CE - Purchase

Step 4 — Enable Enhanced Conversions (in Google Ads UI, not GTM):

In modern Google Ads + gtag.js, Enhanced Conversions is enabled on the
Google Ads side, NOT in the GTM tag itself. Once enabled, the gtag.js
library (loaded by the Google Tag in Step 2) automatically scrapes
email/phone form fields when the awct conversion tag fires — no GTM tag
config needed.

In Google Ads:

  1. Goals → Conversions
  2. Click your Purchase conversion action
  3. "Enhanced conversions" tab
  4. Toggle "Turn on enhanced conversions"
  5. Method: "Google tag"
  6. Implementation: "Automatic collection" (recommended for ~90% of WC
     themes; gtag.js auto-detects <input type="email"> / type="tel"
     fields on the checkout/thank-you page when the conversion fires)
  7. Save

Verify in Google Ads → Goals → Conversions → your Purchase → "Enhanced
conversions" tab. Status should say "Recording enhanced conversions"
within ~24h of the first matched conversion.

(If "Automatic collection" doesn't pick up emails on your theme's
custom checkout, switch to "Manual configuration" and add CSS selectors
for the email / phone / address inputs — same Google Ads UI panel.)

The plugin captures gclid / gbraid / wbraid into 1st-party cookies
(_mcapi_gclid, _mcapi_gbraid, _mcapi_wbraid) the moment a user lands
from an ad click. The Google Tag in Step 2 transfers those into the
_gcl_aw cookie that the awct tag reads. iOS Safari ITP blocks
third-party cookies, so this 1st-party persistence keeps Google Ads
attribution alive on iOS post-2020.


STEP 4 — ADVANCED MATCHING (THE mcapi_identity EVENT)
------------------------------------------------------

WHAT YOU GET

Meta can match more of your ad clicks back to real sales — even when a
cookie gets blocked or cleared — if you also give it a few pieces of
contact information alongside your events: email, phone, name, address.
Meta calls this Advanced Matching, and it is one of the most effective
single changes you can make to your match quality score in Events
Manager. This plugin already prepares that contact information for you;
this step is just wiring it into the Meta Pixel tag you already built
in Step 3A.

HOW IT WORKS

Once a visitor has given you an email or phone number anywhere on the
site — logging in, checking out, using the shipping calculator — the
plugin pushes an mcapi_identity event into the data layer, at most once
per page. It never contains anything readable: every value is SHA-256
hashed before it leaves the server, the same way every other value this
plugin sends is hashed. Nothing extra is leaving your site — it's the
same hashed matching data the plugin already sends via CAPI, made
available to GTM as well.

Unlike every other event in this guide, mcapi_identity is pushed from
the browser once the plugin's own event call finishes, rather than
being written straight into the page. That is deliberate: it stops a
cached copy of the page from handing one visitor's hashed details to
the next visitor who loads it.

The event carries a user_data object with only the fields the visitor
has actually supplied, already hashed, keyed as: em (email), ph
(phone), fn (first name), ln (last name), ct (city), st (state or
region), zp (postcode), country, ge (gender), db (date of birth).

SETUP

1. Create a trigger:

   * CE - Identity  — Custom Event, Event name: mcapi_identity

2. Create a Data Layer Variable for each field you want to send — most
   stores only bother with email and phone, but any of the ten works
   the same way:

   * DLV - Identity Email       — Data Layer Variable Name: user_data.em
   * DLV - Identity Phone       — Data Layer Variable Name: user_data.ph
   * DLV - Identity First Name  — Data Layer Variable Name: user_data.fn
   * DLV - Identity Last Name   — Data Layer Variable Name: user_data.ln
   * DLV - Identity City        — Data Layer Variable Name: user_data.ct
   * DLV - Identity State       — Data Layer Variable Name: user_data.st
   * DLV - Identity Zip         — Data Layer Variable Name: user_data.zp
   * DLV - Identity Country     — Data Layer Variable Name: user_data.country
   * DLV - Identity Gender      — Data Layer Variable Name: user_data.ge
   * DLV - Identity DOB         — Data Layer Variable Name: user_data.db

3. Open the Meta Pixel tag you already have (Step 3A) and find its
   Advanced Matching section. Turn Advanced Matching on, then map each
   field to the Data Layer Variable above: Email to
   {{DLV - Identity Email}}, Phone to {{DLV - Identity Phone}}, and so
   on for whichever fields you created variables for.

4. Add the CE - Identity trigger from step 1 as an extra trigger on
   that same Meta Pixel tag, alongside whatever it already fires on —
   so the Advanced Matching fields refresh as soon as the plugin has
   something hashed to send, not only on the events the tag already
   covers.

That's it. There is no new tag to build — you are adding fields and a
trigger to the Meta Pixel tag that is already there.


SUBSCRIPTION EVENTS (Subscribe / SubscriptionRenewal)
------------------------------------------------------

If you sell WooCommerce Subscriptions and turn on separate Subscribe /
SubscriptionRenewal reporting (Advanced Configuration tab in the plugin
settings), the plugin reports a subscription's first sign-up and each
later renewal to Meta, Pinterest and TikTok under those names instead
of folding every subscription charge into one blended Purchase number —
so sign-ups and renewals show up in Ads Manager as what they actually
are.

That relabeling happens only in what the plugin sends straight to those
ad platforms. The data layer still receives the same purchase event
either way, so the CE - Purchase trigger and the Purchase tags set up
earlier in this guide already cover subscription orders. There is
nothing extra to build in GTM for Subscribe or SubscriptionRenewal.


PUBLISH
-------

After all tags are created, click Submit in the top right corner, then
Publish your container. Verify in GTM Preview that each event fires on the
matching action (add a product to cart, observe AddToCart fire).


CONSENT MODE v2 + CMP-AUTO-BLOCKING
-----------------------------------

For Consent Mode v2 wiring, CMP detection, and the WooCommerce Subscriptions
integration, see the Advanced Configuration tab inside the plugin settings —
those settings live in the plugin admin, not in GTM.
