Skip to main content

Shopify Implementation Guide

DATA Reshape installs on Shopify with two assets that work together:

  1. A theme snippet included in theme.liquid — runs in the storefront window.
  2. A Custom Pixel added in Shopify Admin (Customer events) — the only surface in Shopify where checkout / thank-you / order status events are observable.

The two assets share the same configuration (subdomain + script ID + mode). One config controls both.

Terminology

Throughout this page, global tracking code (or tracking snippet) refers to the small inline JavaScript block you paste into the theme snippet and the Custom Pixel — the bootstrap. The script it loads from your subdomain at runtime is referred to abstractly as the runtime script.

Prerequisites

Required before implementation

Only install after your custom domain and SSL certificate are active. The tracking subdomain (e.g. dre2.YOUR_DOMAIN.TLD) must share the same root domain as the storefront for cookies and CORS to work.

You will need:

  • Custom tracking subdomain — e.g. dre2.YOUR_DOMAIN.TLD
  • Script ID — provided by the DATA Reshape team
Implementation support — DATA Reshape can do this for you

You do not have to install everything by yourself. DATA Reshape provides hands-on implementation support and will perform the setup, audit, verification, and per-destination configuration on your store. To enable that, please grant us the following so we can do the work and run the checks end-to-end:

  • Collaborator access (not staff) — accept the collaborator access request that DATA Reshape sends from Shopify, and provide the collaborator request PIN displayed under Settings → Users → Security. We do not accept staff accounts; collaborator is the standard model and can be revoked at any time.
  • Theme access — required to install / update the global tracking code in theme.liquid and the optional product-page enrichment block.
  • Apps access — required to audit and adjust the sales channels (Facebook & Instagram, Google, TikTok) and any other apps that may push to managed destinations.
  • Customer events access — required to create, configure, and validate the DATA Reshape Custom Pixel.
  • Notifications access — required to inspect order, checkout and customer notification templates that may carry tracking parameters or trigger destination events.
  • Customer privacy access — required to verify the consent banner configuration, the Shopify-native consent signals, and to confirm that consent state is correctly propagated to the DATA Reshape Custom Pixel and downstream destinations.

After access is granted, DATA Reshape will run the installation, the cleanup of duplicate destination code, the privacy settings on the Custom Pixel, the sales-channel adjustments, and the end-to-end verification — and report back when everything is live. Access can be revoked at any time once the work is done.

Operating modes

Pick the mode that fits your store. The choice is set via the parent field in the shared config.

The runtime script is loaded in the storefront parent window via the theme snippet. The Custom Pixel observes the relevant events and forwards them to the storefront, where the full DATA Reshape SDK consumes them. On surfaces the storefront cannot reach (checkout, thank-you, order status), the Custom Pixel takes over and runs the runtime script on its own. All the coordination between the two is handled internally — you do not need to wire anything.

Use it when you can edit theme.liquid and want the richest behavior on non-checkout pages (full DOM access, in-page consent banner integration, etc.).

Pixel-only mode (parent: 0)

The runtime script runs only inside the Custom Pixel on every page. The theme snippet, if present, detects parent: 0 and exits — no scripts in the storefront. The pixel becomes the sole tracking surface.

Use it when you cannot or do not want to inject scripts in the theme (security policy, store-front lockdown, etc.). Trade-off: no DOM access on non-checkout pages.

Step 1 — Add the theme snippet

Remove existing destination code first

Before installing the snippet, delete or comment out every other piece of code in the theme (and every other Custom Pixel / Shopify app) that talks to a destination DATA Reshape manages on this account — Meta Pixel / Conversions API, Google Tag (gtag.js, GTM), TikTok Pixel, Pinterest Tag, Snap Pixel, Klaviyo onsite tracking, etc.

DATA Reshape owns the full lifecycle for every connected destination — pixel fire, server-side conversion API call, consent enforcement, deduplication. If the original theme code or a parallel pixel also fires for the same destination, you will get double events, double conversions, inflated CPA, and inconsistent attribution — the two emitters will not deduplicate against each other.

Concrete checklist:

  • In theme.liquid / layout/*.liquid — search for fbq(, gtag(, ttq., pintrk(, snaptr(, any inline <script> containing pixel IDs (G-..., GTM-..., Meta numeric IDs, TikTok pixel_code, etc.). Delete or comment out.
  • In Customer events (where you're about to add this Custom Pixel) — disable or remove any other custom pixel for the same destinations.
  • In Apps — uninstall or pause apps only if tracking is their sole function. If the app also provides other services you actively use (catalog sync, ad management, shop pages, merchant feed, customer support widget, etc.), keep it installed and turn off only the tracking / data-sharing setting inside the app. See the next callout for sales channels specifically.
  • In checkout.liquid (Plus only) and in additional_scripts (Plus) — same audit.

The only tracking surface for managed destinations on this store should be DATA Reshape. Anything else either duplicates or contradicts what DATA Reshape sends server-side.

Skipping this cleanup is the single most common cause of data anomalies on Shopify installs — major duplication of events and conversions, double-counted revenue, mismatched attribution between destinations, inflated CPA in ad platforms, dedup logic broken end-to-end. These issues are often noticed only weeks later in destination dashboards and are painful to unwind. Do the audit before you go live.

Shopify sales channels (Facebook & Instagram, Google, TikTok) — adjust settings, don't uninstall

The official sales channel apps (Facebook & Instagram, Google, TikTok) do more than tracking — they sync your product catalog, manage shop on Facebook, push the merchant feed to Google Merchant Center, etc. If any of those non-tracking features are in use, keep the channel installed and turn off only the tracking / data-sharing portion so it doesn't run in parallel with DATA Reshape. Uninstall the channel only if you are not using anything from it.

For each channel app that maps to a destination DATA Reshape manages on your account, open the app's Settings → Share data section and set the data-sharing mode to off / disabled. Catalog sync, shop pages, merchant feed and other non-tracking features can stay on.

Example — Facebook & Instagram sales channel:

SettingRequired when DATA Reshape handles Meta trackingWhy
Share dataData sharing is offTurning this on would make Shopify fire the Meta Pixel + advanced matching + Conversions API in parallel with DATA Reshape, producing double events and breaking deduplication. DATA Reshape already covers all of these from a single, deduplicated pipeline.
CatalogCatalog in sync (keep on)Catalog sync feeds product data into Meta for Shops, ads and dynamic creatives — it doesn't emit tracking events. Safe and recommended to leave enabled.

Apply the same logic to the Google sales channel (turn off Google Tag / Enhanced Conversions data sharing, keep Merchant Center feed) and the TikTok sales channel (turn off Pixel / Events API data sharing, keep catalog + Shop integrations).

If DATA Reshape does not manage a particular destination on your account (e.g. Meta tracking handled by DATA Reshape, but Pinterest is left to the official Pinterest channel), leave that channel's data sharing on. The rule applies per destination, not blanket.

Recommended pattern: create a dedicated Liquid snippet so the tracking code lives in one isolated file that's trivial to find, review, and update.

1a. Create the snippet file

Open Shopify Admin → Online Store → Themes → … → Edit code → in the left tree, scroll to SnippetsAdd a new snippet → name it dataReshapeCode (file becomes snippets/dataReshapeCode.liquid). Paste this content:

{%- comment -%} DO NOT MODIFY BELOW {%- endcomment -%}
<script>
const Reshape = window.Reshape = {
shopify: {
config: [
{ sub: 'dre2.YOUR_DOMAIN.TLD', id: 'YOUR_SCRIPT_ID', parent: 1 }
]
}
};
(function(R,e,s,h,a,p,E){function g(x){var c=(""+x).split("."),d=/\.co\.|\.com\.|\.org\.|\.edu\.|\.net\.|\.asn\./.test(x)?3:2;return c.slice(-d).join(".")}var r=g(R.location.hostname),c,i,S=h.shopify,C=S.config;for(i=0;i<C.length;i++){if(g(C[i].sub)===r){c=C[i];break}}if(!c){console.warn("[DATA Reshape] Domain not configured:",R.location.hostname);return}S.parent=c.parent;if(!c.parent)return;var _r=R._reshape=R._reshape||[];R.addEventListener("message",function(v){if(v.data&&v.data.reshape)_r.push(v.data.reshape)});h.setCookie=function(n,v,t,d){try{e.cookie=n+"="+v+";max-age="+t+";domain="+d+";path=/;SameSite=None;Secure"}catch(e){}};h.id=c.id;h.cdn=c.sub;h.sts=new Date().getTime();E=e.getElementsByTagName(s)[0];var P=e.createElement(s);P.async=true;P.src="https://"+c.sub+"/main.js?id="+c.id;E.parentNode.insertBefore(P,E);(function A(n){if(R.Shopify&&R.Shopify.analytics&&R.Shopify.analytics.publish){R.Shopify.analytics.publish("reshape:parent",{})}else if(n<60){setTimeout(function(){A(n+1)},50)}})(0)})(window,document,"script",Reshape);
</script>

Replace dre2.YOUR_DOMAIN.TLD and YOUR_SCRIPT_ID with the values provided to you, then save.

1b. Include it in theme.liquid

Open layout/theme.liquid (or whichever layout file your theme uses as the global wrapper) and add the render call immediately below {{ content_for_header }}, wrapped in marker comments so future editors don't move or delete it accidentally:

{{ content_for_header }}

{%- comment -%} DATA RESHAPE TRACKING (PLEASE DO NOT DELETE OR MOVE) {%- endcomment -%}
{% render 'dataReshapeCode' %}
{%- comment -%} END DATA RESHAPE TRACKING {%- endcomment -%}

Save the file.

Position matters

The snippet must run after {{ content_for_header }} so Shopify-injected scripts initialize first. Placing it inside the <head> before content_for_header can leave the snippet initializing before Shopify is ready, delaying the coordination between the theme snippet and the Custom Pixel.

Pixel-only setup

If you are deploying in pixel-only mode, set parent: 0 in the config. The snippet will still render, detect the mode, and exit without injecting anything in the storefront. Keeping the snippet rendered (even in pixel-only mode) makes it trivial to flip back to mixed mode later — just change parent: 1 in the snippet file, no theme edit needed.

Step 2 — Install the Custom Pixel

In Shopify Admin go to Settings → Customer events → Add custom pixel. Name it DATA Reshape, configure the Customer privacy block as described in the section below, and paste this code:

// == CONFIG =========
const Reshape = window.Reshape = {
shopify: {
id: '', // leave empty unless DATA Reshape support asks you to set it
config: [
{ sub: 'dre2.YOUR_DOMAIN.TLD', id: 'YOUR_SCRIPT_ID', parent: 1 }
]
}
};

// == PIXEL ==========
// NOTE: Do not modify below
(function(R,e,s,h,a,p,E){
function g(x){var c=(""+x).split("."),d=/\.co\.|\.com\.|\.org\.|\.edu\.|\.net\.|\.asn\./.test(x)?3:2;return c.slice(-d).join(".")}
var l=a?.context?.document?.location||{},o=l.hostname||"",f=l.pathname||"",w=l.origin||"*",r=g(o),c,i,S=h.shopify,C=S.config;
for(i=0;i<C.length;i++){if(g(C[i].sub)===r){c=C[i];break}}if(!c){console.warn("[DATA Reshape] Domain not configured:",o);return}
h.id=c.id;h.cdn=c.sub;h.sts=new Date().getTime();S.api=api;S.parent=c.parent;i=f&&(f.indexOf(S.id)===1||f.indexOf("checkout")===1||f.indexOf("orders")===1);
var t=c.parent&&!i,_r=R._reshape=R._reshape||[];p.subscribe("all_events",function(d){_r.push(d);if(t){try{parent.postMessage({reshape:d},w)}catch(e){}}});
function M(){E=e.getElementsByTagName(s)[0];var P=e.createElement(s);P.async=true;P.src="https://"+c.sub+"/main.js?id="+c.id;E.parentNode.insertBefore(P,E);}
if(!c.parent||i){M()}else{var y=0;p.subscribe("reshape:parent",function(){y=1});setTimeout(function(){if(!y){S.parent=0;t=0;M()}},1e3)}
})(window,document,"script", Reshape, init, analytics);

Replace dre2.YOUR_DOMAIN.TLD and YOUR_SCRIPT_ID with the values provided to you. Leave shopify.id as the empty string '' — it is an internal hint used only for detecting a legacy Shopify URL pattern. DATA Reshape support will let you know if your store needs a non-empty value. Save and Connect the pixel.

Keep both configs in sync

The config array in the theme snippet and the Custom Pixel must contain the same entries. If they drift, the storefront and the pixel will disagree on parent mode or load the wrong script ID.

Customer privacy settings

In the Custom Pixel edit screen, the Customer privacy block must be set as follows. DATA Reshape does its own consent enforcement downstream — it reads the Shopify-native consent signal automatically, enforces per-destination consent categories (analytics / personalization / marketing), and applies the operating mode configured for your account. Letting Shopify gate the pixel here would short-circuit that — events would never reach DATA Reshape, so there would be nothing to enforce on.

FieldValueWhy
PermissionNot required (The pixel will always run)The pixel itself must always run so DATA Reshape can apply its own per-account, per-destination consent rules (default-denied, restricted pings, replay on consent, etc.). See Consent Overview for the operating modes.
Data saleData collected does not qualify as data sale (The pixel will collect data when the customer opts out of their data being sold)The pixel does not directly sell data — it streams to your configured destinations under your account's privacy configuration. CCPA/CPRA opt-out is honored by DATA Reshape per destination, not by suppressing the pixel here.
Why not "Required" or "Data sale"?

Selecting Required would make Shopify suppress the pixel based on its own consent banner state, before any event reaches DATA Reshape — meaning DATA Reshape would observe nothing for opted-out visitors, and would not be able to apply Anonymous Ping, Replay-on-consent, or any other operating mode that depends on seeing the events first.

Selecting either Data sale variant would similarly let Shopify drop events client-side for opted-out US visitors, bypassing the per-destination opt-out signaling (Meta data_processing_options, TikTok limited_data_use, etc.) that DATA Reshape sends to each destination on your behalf.

The intent is not to ignore consent — it is to centralize the enforcement in DATA Reshape, which has visibility into every destination and applies the right behavior per category and per visitor.

Configuration reference

The same shape is used in both places:

Reshape.shopify.config = [
{ sub: 'dre2.YOUR_DOMAIN.TLD', id: 'YOUR_SCRIPT_ID', parent: 1 }
];
FieldTypeRequiredPurpose
substringyesTracking subdomain that serves the runtime script. Must share the storefront's root domain. The match also covers www., shop., etc.
idstringyesTracking script ID assigned by DATA Reshape. Used as ?id=... on the runtime script URL.
parentnumberoptional (default 1)1 = mixed mode (runtime script in storefront + Custom Pixel coordinating with it). 0 = pixel-only mode (runtime script inside the Custom Pixel only).

Multi-store config (one merchant, multiple country shops)

The right entry is auto-selected at runtime by matching the current hostname's root domain against sub. One snippet + one pixel can serve every shop.

config: [
{ sub: 'dre2.yourdomain.ro', id: 'SCRIPT_ID_RO', parent: 1 },
{ sub: 'dre2.yourdomain.eu', id: 'SCRIPT_ID_EU', parent: 0 },
{ sub: 'dre2.YOUR_DOMAIN.TLD', id: 'SCRIPT_ID_COM' } // parent defaults to 1
]

Pushing custom events

Beyond the events the Custom Pixel and the optional Liquid block produce automatically, you can push any of the events documented in Events Referencelead_created, newsletter_subscribed, click, custom interactions, etc.

DATA Reshape only accepts events from a single explicit channel

By design, DATA Reshape does not process arbitrary page events — it would let unrelated scripts pollute your data, double-count, or send malformed payloads to destinations. The only way to feed DATA Reshape from your own code is the channel below; everything else is ignored.

The right method depends on which surface your code is running on. In mixed mode (parent: 1), most theme code runs in the storefront so you use reshape.push(...) there; code running inside the Custom Pixel still uses the pixel-side method below. In pixel-only mode (parent: 0), only the pixel-side method is available.

Available when parent: 1 is configured. Use it from theme.liquid, any other Liquid template, theme JS files, or third-party storefront apps:

window.reshape = window.reshape || [];
reshape.push({
event: {
name: "lead_created",
value: 250,
currency: "USD",
id: "lead_abc123"
},
user: {
email: "[email protected]",
first_name: "Example First Name"
}
});

Optional — product page enrichment

The Custom Pixel covers the standard storefront and checkout events automatically (product_viewed on PDP, product_added_to_cart, checkout_started, checkout_completed, etc.). On Online Store 2.0 themes you can additionally push a richer product_viewed payload from theme.liquid so destinations receive variant images, categories, parent SKU and logged-in customer data — fields the Custom Pixel does not surface on its own.

Paste this immediately after the snippet block, still in theme.liquid:

{%- comment -%}
=====================================================================
DATA Reshape — product page enrichment (optional)
---------------------------------------------------------------------
Sends a richer `product_viewed` payload from the storefront when a
product template is rendered. Includes variant images, categories,
parent SKU and logged-in customer data — fields the Custom Pixel
cannot surface on its own.

Deduplicated server-side against the Custom Pixel's `product_viewed`,
so adding this block never produces double counts.

Safe to remove or comment out — DATA Reshape will keep working from
the Custom Pixel alone, with a lighter `product_viewed` payload.
=====================================================================
{%- endcomment -%}

{%- if template contains 'product' -%}
{% liquid
assign created_timestamp = product.created_at | date: '%s' | times: 1000
assign total_price = 0
for variant in product.variants
assign total_price = total_price | plus: variant.price
endfor
assign average_price = total_price | times: 1.0 | divided_by: product.variants.size | times: 0.01
%}
<script>
window.reshape = window.reshape || [];
window.reshape.push({
"event": {
"name": "product_viewed",
"value": {{ average_price | round: 2 }},
"currency": {{ shop.currency | json }}
},
"context": {
"environment": "prod",
"page_type": "product"
},
"products": [
{% for variant in product.variants %}
{
"id": "{{ variant.id }}",
"parent_id": "{{ product.id }}",
"sku": {{ variant.sku | json }},
"parent_sku": {{ product.variants.first.sku | json }},
{% if variant.barcode != blank %}"gtin": {{ variant.barcode | json }},{% endif %}
"name": {{ product.title | json }},
"parent_name": {{ product.title | json }},
"brand": {{ product.vendor | json }},
"type": {% if product.variants.size > 1 %}"variable"{% else %}"simple"{% endif %},
"price_base": {% if variant.compare_at_price > 0 %}{{ variant.compare_at_price | times: 0.01 | round: 2 }}{% else %}{{ variant.price | times: 0.01 | round: 2 }}{% endif %},
"price": {{ variant.price | times: 0.01 | round: 2 }},
"currency": {{ shop.currency | json }},
"tax_included": {{ shop.taxes_included }},
"quantity": 1,
"stock_status": {{ variant.available }},
"created_at": {{ created_timestamp }},
"url": {{ variant.url | prepend: shop.secure_url | json }},
"parent_url": {{ product.url | prepend: shop.secure_url | json }},
"image": {{ variant.featured_image.src | default: product.featured_image.src | image_url: width: 1024 | prepend: 'https:' | json }},
"images": [
{% for image in product.images limit: 5 %}
{{ image.src | image_url: width: 1024 | prepend: 'https:' | json }}{% unless forloop.last %},{% endunless %}
{% endfor %}
],
"category": {{ product.type | json }},
"categories": [
{% for collection in product.collections limit: 5 %}
{ "name": {{ collection.title | json }}, "id": "{{ collection.id }}" }{% unless forloop.last %},{% endunless %}
{% endfor %}
],
"properties": {
{% assign variant_values = "" %}
{% for option in variant.options %}
{% if option %}
{% if variant_values != "" %}{% assign variant_values = variant_values | append: " / " %}{% endif %}
{% assign variant_values = variant_values | append: option %}
{% endif %}
{% endfor %}
"variant": {{ variant_values | json }}
}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
{% if customer %},
"user": {
"id": "{{ customer.id }}",
"email": {{ customer.email | json }},
{% if customer.phone %}"phone": {{ customer.phone | json }},{% endif %}
"first_name": {{ customer.first_name | json }},
"last_name": {{ customer.last_name | json }},
{% if customer.default_address %}
"country": {{ customer.default_address.country | json }},
"region": {{ customer.default_address.province | json }},
"city": {{ customer.default_address.city | json }},
"street": {{ customer.default_address.street | json }},
"postal_code": {{ customer.default_address.zip | json }},
{% endif %}
"orders_total_number": {{ customer.orders_count }},
"orders_total_value": {{ customer.total_spent | times: 0.01 | round: 2 }},
"created_at": {{ customer.created_at | date: '%s' | times: 1000 }}
}
{% endif %}
});
</script>
{%- endif -%}

DATA Reshape deduplicates the enriched push against the Web Pixels product_viewed automatically, so adding this block never produces double counts.

Why these permissions?

AssetWhy
Theme code editTo insert the snippet in theme.liquid for mixed mode.
Customer eventsThe only surface in Shopify where checkout / thank-you / order status events are observable.
Partner access (if requested)Lets the DATA Reshape team install the snippet and pixel on your behalf without exposing your admin credentials.

Verification

End-to-end verification is performed by the DATA Reshape team. Reach out at [email protected] once the snippet and the Custom Pixel are installed, and we will run the confirmation tests, validate the data flowing to each connected destination, and confirm the configuration is correct.

Why DATA Reshape verifies the data

The tracking surface is built privacy-first: payloads are obfuscated, PII is normalized and hashed before it leaves the browser, sensitive parameters are encrypted at rest, identity is partitioned per account, and destination-specific protections (such as opt-out signals, data-minimization filters, and limited-use modes) are applied server-side before any downstream call.

Because of these advanced privacy and tracking protections, the data observable from the outside is intentionally not enough to validate quality on your own. DATA Reshape is the only party with the visibility needed to confirm that events, identifiers, conversions, and destination deliveries are correct end-to-end.

Privacy by design is a feature of the platform, not an inconvenience — it's what keeps the implementation compliant out of the box and protects your customers' data regardless of which destinations you connect later.

Troubleshooting

Most installation-time issues you can fix yourself surface as a single browser console message:

SymptomLikely causeFix
[DATA Reshape] Domain not configured: … in the browser consoleThe active hostname's root doesn't match any sub entryAdd the right sub for this store, or correct a typo. The match uses root domain only.

For anything beyond this — events that don't seem to arrive, deduplication concerns, destination-side discrepancies, or any other doubt about data quality — please contact [email protected]. By design, the only reliable view into event flow and destination delivery is the internal one; we'll confirm the state, identify the cause, and guide the fix.

Next steps

  1. Confirm destinations — see Destinations for per-platform setup.
  2. Add custom events — see Events Reference for the full catalog of events DATA Reshape can capture on Shopify beyond what the Custom Pixel covers automatically.
  3. Validate consent flow — see Consent Overview for how Shopify-native consent signals are picked up automatically.