> For the complete documentation index, see [llms.txt](https://docs.adpage.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.adpage.io/faq/marketing-optimization/shopify-shop-campaigns-and-server-side-tracking.md).

# Shopify Shop Campaigns and server-side tracking

Understand why Shop Campaign orders need backend attribution, delayed tag handling, and order-level deduplication.

## How the two models differ

Server-side tracking and Shopify Shop Campaigns collect conversion data differently. Traditional tracking starts in the shopper's browser. Shop Campaign attribution starts in Shopify's backend.

This difference affects attribution, ingestion timing, and reporting. It also changes how you prevent duplicate revenue.

### Traditional server-side tracking

Traditional server-side tracking uses a web-first, event-driven architecture. A visitor opens your storefront, such as `yourstore.com`. The browser loads a web container, typically web Google Tag Manager.

The web container captures browser-level identifiers. These may include `_fbp`, `_ga`, IP address, and user agent. It sends events to a server container through HTTP requests.

The server container validates, transforms, and forwards those events. Destinations can include Meta Conversions API, Google Analytics 4, and a data warehouse such as ClickHouse.

```
[Visitor browser]
        │
        ▼
[Storefront + web GTM]
        │ HTTP request
        ▼
[Server-side GTM] ──┬──> Meta CAPI / Google Analytics
                    └──> Data warehouse
```

### Shopify Shop Campaigns

Shopify Shop Campaigns uses an off-site, pay-per-sale model. Campaigns can surface products and offers beyond your storefront:

* **Shop app and web:** Discovery feeds, offer tabs, search results, and `shop.app`.
* **Shopify Product Network:** Promoted listings in participating Shopify stores.
* **Syndicated channels:** Placements on external networks through Shopify-managed ad accounts.

The conversion can happen in native Shopify checkout or an embedded Shop Pay component. The shopper may never load your storefront or web container.

```
[Off-site placement]
        │
        ▼
[Shop Pay checkout]
        │
        ▼
[Shopify backend] ──> [Campaign tag added asynchronously]
        │
        ▼
[Webhooks / Admin API] ──> [Data warehouse]
```

## Technical comparison

| Attribute           | Traditional server-side tracking           | Shopify Shop Campaigns                                    |
| ------------------- | ------------------------------------------ | --------------------------------------------------------- |
| Conversion location | Your storefront                            | Shop app, `shop.app`, Product Network, or native checkout |
| Primary trigger     | Browser event forwarded to server GTM      | Shopify backend order events                              |
| Common identifiers  | Browser cookies, IP address, user agent    | Order ID, Shopify customer ID, email, shipping address    |
| GTM during purchase | Web and server containers process requests | The purchase can bypass both containers                   |
| Attribution basis   | Click, impression, or multi-touch signals  | Offer or action-based attribution                         |
| Billing model       | Usually PPC or CPM                         | Pay per confirmed sale                                    |
| Ad account          | Merchant-owned account                     | Shopify-managed account for syndicated placements         |
| Ingestion timing    | Near real time                             | Asynchronous; a campaign tag can arrive later             |

## Implementation requirements

### Handle delayed campaign tags

Shopify creates the order immediately. It can apply the campaign-identifying tag later, after attribution validation completes. The tag may appear up to eight hours after purchase.

{% hint style="warning" %}
**Avoid a one-time order import.** An `orders/create` webhook can arrive before the campaign tag. Classifying the order immediately may label it as direct or organic.
{% endhint %}

Use one of these approaches:

{% stepper %}
{% step %}

#### Subscribe to `orders/updated`

Re-evaluate the order tags whenever Shopify updates the order.
{% endstep %}

{% step %}

#### Poll the Admin API after a delay

Retrieve the order again through the Shopify Admin API. Run this job 8–12 hours after creation.
{% endstep %}
{% endstepper %}

### Step-by-step server-side implementation

Use the standard AdPage Webhook Matching flow for Shop Campaign orders. The webhook is the **Trigger** side. A browser `begin_checkout` event is the **Prepare** side.

{% stepper %}
{% step %}

#### Configure the AdPage Webhook Client

Install and configure the **AdPage Webhook Client** in your server GTM container. It receives and parses the Shopify order webhook.

Configure Shopify's `orders/updated` webhook to use the endpoint processed by this client. Do not route the raw Shopify request directly to GA4, Meta CAPI, or ClickHouse tags.

Follow [Webhook Matching](https://docs.adpage.io/optimize-your-setup/webhook-matching) to install the **AdPage Event Notifier** template and configure the webhook client.
{% endstep %}

{% step %}

#### Configure Prepare and Trigger

Create two **AdPage Event Notifier** tags:

* **Prepare:** Fire on the storefront `begin_checkout` event.
* **Trigger:** Fire on the Shopify webhook event processed by the AdPage Webhook Client.

Set the Trigger transaction ID to the webhook's `transaction_id`. Both tags must use the same platform preset and BasketKey.

For a native Shopify setup, use the **Shopify** preset with `cart_token`. When AdPage Tagging is installed, use **AdPage Tagging (universal)** with `user_id`.

{% hint style="warning" %}
**Do not map the BasketKey to GA4 `user_id`.** It is only used to match Prepare and Trigger. Use a stable, real GA4 User-ID only when your site already sets it consistently.
{% endhint %}
{% endstep %}

{% step %}

#### Handle the tag delay and duplicate updates

Shopify can apply `Shop Cash offers acquired` up to eight hours after order creation. An `orders/updated` webhook can also fire several times for one order.

Set the Event Notifier Trigger to run only when `payload.tags` contains `Shop Cash offers acquired`. Use the order `transaction_id` as the event and deduplication key.

Webhook Matching deduplicates the matched conversion. It also combines available browser context with the Shopify order.
{% endstep %}

{% step %}

#### Validate matching before activation

Publish the Prepare and Trigger configuration. Let it collect data for several days, then check **Webhook Matching → Match health** in your AdPage container.

Continue when the matching rate is above 90%. If it is lower, improve the shared identifier or review the matching configuration before enabling downstream purchase tags.
{% endstep %}

{% step %}

#### Route the matched purchase event

Webhook Matching sends the matched payload to the server GTM `/mp` endpoint. Create a **GA4 Measurement Protocol** client for this path.

Block `purchase` events in the regular GA4 trigger. Create a new trigger for requests handled by the Measurement Protocol client. Use that trigger for GA4, Meta CAPI, ClickHouse, and other downstream tags.

Set `channel` to `shop_campaigns` for warehouse reporting. Use `transaction_id` as Meta's `event_id` to deduplicate the browser Pixel and CAPI event.
{% endstep %}
{% endstepper %}

```
[Storefront `begin_checkout`]
        │
        ├──> Event Notifier Prepare
        │
[Shopify `orders/updated`]
        │
        ├──> AdPage Webhook Client
        └──> Event Notifier Trigger
                    │
                    ▼
        [AdPage Webhook Matching]
                    │ Matched payload
                    ▼
[Server GTM `/mp` endpoint]
        │
        └──> GA4, Meta CAPI, ClickHouse, and other tags
```

{% hint style="warning" %}
**Shop Campaign orders may not have a browser Prepare event.** They can therefore remain unmatched. Review these orders in Match health. Use trigger-only forwarding only after reviewing its weaker attribution and consent implications.
{% endhint %}

### Server GTM: benefits and trade-offs

| Benefits                                                                                                              | Trade-offs and requirements                                                                                                                      |
| --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Unified architecture:** Web events, conversion APIs, and warehouse delivery use the same server GTM infrastructure. | **Repeated webhooks:** `orders/updated` can fire multiple times. Configure the Event Notifier Trigger carefully.                                 |
| **Matched payload:** The matched event combines available browser context with the Shopify order.                     | **Limited browser signals:** Off-site Shop Campaign purchases may have no Prepare event or browser identifiers.                                  |
| **Controlled activation:** Match health lets you validate quality before enabling purchase tags.                      | **Fallbacks need review:** Trigger-only and probabilistic matching use weaker signals. Enable them only after reviewing attribution and consent. |

### Classify the channel from order tags

Native Shop Campaign orders can bypass storefront UTM parameters such as `utm_source` and `utm_medium`. Standard analytics rules may therefore leave the channel unassigned.

{% hint style="info" %}
**Recommended rule:** Evaluate order tags in your transformation layer. When `Shop Cash offers acquired` is present, map the channel to a dedicated value such as `shop_campaigns`.
{% endhint %}

### Deduplicate cross-channel reporting

Shop Campaigns can overlap with other paid channels. A single customer journey may produce several valid attribution claims.

{% stepper %}
{% step %}

#### A shopper engages with a Meta ad

Meta records a click or view signal.
{% endstep %}

{% step %}

#### The shopper purchases through Shop

The customer later sees a Shop Campaign offer and completes checkout with Shop Pay.
{% endstep %}

{% step %}

#### Meta claims the conversion

Meta Pixel or Conversions API attributes the conversion within its attribution window.
{% endstep %}

{% step %}

#### Shopify attributes the offer

Shopify attributes the conversion to the campaign offer and applies its pay-per-sale fee.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
**Use `order_id` as the primary deduplication key.** Apply it across every sales source to prevent revenue inflation.
{% endhint %}

### Reference pipeline

```
[Native Shopify conversion]
        │
        ▼
[Order created without campaign tag]
        │
        ▼
[Campaign tag added within 0–8 hours]
        │
        ├──> `orders/updated` webhook
        │
        └──> Or poll the Admin API after 8 hours
                    │
                    ▼
        [AdPage Webhook Client]
        - Process the order webhook
        - Event Notifier Trigger checks the campaign tag
        - Match with the browser Prepare event
                    │
                    ▼
        [Measurement Protocol client]
        - Receive the matched payload at `/mp`
        - Map channel to `shop_campaigns`
        - Send to ClickHouse and selected ad platforms
```

### Checklist

* Process `orders/updated` after the campaign-tag delay.
* Configure AdPage Event Notifier Prepare and Trigger tags.
* Check Match health before enabling downstream purchase tags.
* Classify tagged orders as `shop_campaigns`.
* Use `transaction_id` for purchase and Meta event deduplication.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.adpage.io/faq/marketing-optimization/shopify-shop-campaigns-and-server-side-tracking.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
