Logo of TAGGRS, written in blue and with a small favicon
HomeServer-side TrackingMeta CAPI Gateway
EnglishDeutsch
SERVER-SIDE TRACKING
Get started
Get started with TAGGRSSet up Google Tag ManagerConfigure the subdomainAdd the GTM Data LayerConfigure GTM transformationsTest the setupDebuggingAnalytics dashboard
Migrate from Google CloudMigrate from hosting
Shortcuts
GTM Copy PasteReady-made templates
GA4 Server-side Tracking
Setup in GTMCreate GA4 Event TagsGA4 tag setup in server containerE-commerce events in GTM
Google Ads Server-side Tracking
Install Conversion LinkerSet up Conversion TrackingConfigure Enhanced ConversionsDeploy Remarketing TagsInstall Offline Conversions
Facebook Server-side Tracking
Set Meta PixelImprove your EMQ ScoreInstall Meta CAPIMeta Events Deduplication
LinkedIn Server-side Tracking
Install LinkedIn Insight TagSet up LinkedIn CAPILinkedIn Events Deduplication
TikTok Server-side Tracking
Set up TikTok PixelInstall TikTok Events APITikTok Events Deduplication
Pinterest Server-side Tracking
Set up Pinterest TagConfigure Pinterest Conversions APIPinterest Events Deduplication
Snapchat Server-side Tracking
Set up Snap PixelSnapchat Conversions APISnapchat Events Deduplication
TAGGRS Tracking Tags and Tools
Tracking TagsGoogle Service Account integrationProfit TrackingData Enricher ToolWebhooks TesterEnhanced Tracking ScriptMulti Domain ToolClick ID RecoveryConsent Approval GraphProfit Feed Tool
Configurations
Billy Grace Server-side TrackingLeadPages Server-side TrackingPiwik PRO Server-side TrackingCDN Server-side TrackingShopify Server-side TrackingActiveCampaign Server-side TrackingKlaviyo Server-side TrackingSpectacle Server-side TrackingEulerian Server-side TrackingSame origin tracking with Cloudflare
Server-side Tracking for e-commerce
Shopify Data LayerShopware Data LayerMagento Data LayerWooCommerce Data LayerPrestashop Data LayerLightspeed Data Layer
Consent Management server-side
Activate Consent ModeConfigure AxeptioConfigure Cookie Confirm
META CAPI GATEWAY
ACCOUNT SETTINGS
User roles and accessSSO

Same origin tracking with a Cloudflare Worker

Serve your TAGGRS tracking script from the same origin as your website, not just the same site. A tracking subdomain like sst.yourdomain.com is same-site, but it is still a separate origin. Same-site already provides a first-party cookie context, but Safari may still apply tracking-subdomain IP and CNAME-cloaking checks.

Serving tracking from a path on the website’s own origin avoids these separate-host checks, helping server-set cookies retain their intended lifespan instead of being capped at seven days. It also removes the separate tracking hostname, reducing exposure to hostname-based ad-blocking rules.
Logo of TAGGRS Server-side Tracking: a light blue circle with two blue angle brackets
Same-site vs same-origin
‍
To a browser, these mean different things:

- Same-site only requires the same registrable domain. yourdomain.com and sst.yourdomain.com are same-site because both sit under yourdomain.com. 

- Same-origin is stricter: the protocol (https), full hostname and port must all match exactly. So, sst.yourdomain.com is same-site as your main domain but a separate origin, because the hostname differs.  

The browser reserves its highest trust for resources that share the page's exact origin which, as you'll see below, is what protects your cookies on iOS.

Why this matters

Server-side Tracking already moves your data collection off the browser and onto your own server container, and TAGGRS's tracking infrastructure is resistant to ad blockers out of the box thanks to the Enhanced Tracking Script (ETS v3). The bigger reason to load everything from the same origin is cookie lifespan on iOS. Since Safari 16.4 in April 2023, Safari caps your server-set first-party cookies at 7 days unless the host that sets the cookie shares an IP range (specifically, the first half of the IP address) with your main website. A separate tracking subdomain like sst.yourdomains.com points at different infrastructure (your TAGGRS container), so the IP ranges don't match and Safari applies the cap. As a result, your 1- or 2-year identity cookie becomes a 7-day one, and any iOS visitor who doesn't return within the week is counted as new. With same-origin, every resource goes through Cloudflare and resolves to the same IP range, so the check passes and cookies keep their full lifespan. Because all iOS browsers run on Safari's engine, this applies to your entire iOS audience.

You can address this by loading everything from a path on your primary domain. For example, instead of metrics.yourdomain.com you serve tracking from yourdomain.com/metrics. There is no separate tracking hostname for browsers or blockers to recognize, so the request looks like any other first-party asset on your site. In practice, it can help recover a portion of traffic lost to hostname-based blocking and keep cookies in a first-party context.

This guide uses a Cloudflare Worker as a lightweight reverse proxy. You pick one path segment, such as /metrics. The Worker forwards everything under that path to your TAGGRS tracking host and strips the path, so TAGGRS still sees its normal URLs. The tracking script reads its own address in the browser and sends events and assets under the same path.

Logo of TAGGRS Server-side Tracking: a light blue circle with two blue angle brackets
This is an alternative to the standard domain routing setup. It assumes you already have a working TAGGRS product, a server container, and a tracking snippet live on your site. This guide only changes how that snippet is served.

Before you begin

You'll need:

  • A domain on Cloudflare
  • DNS records set to Proxied (orange cloud icon), not DNS only
  • Your Product ID (10 characters, from your TAGGRS dashboard)
  • Your tracking host — the hostname in your current snippet (for example sst.yourdomain.com or sst.taggrs.io), without https://
  • A single path segment you control, for example metrics, data, or _via. Do not pick a prefix of a real page on your site. A path of shop would also catch /shopping-cart.

Set aside about 15 minutes. The path mapping lives in Cloudflare. You do not change Product ID routing inside the TAGGRS dashboard.

The examples below use /metrics but in your implementation avoid obvious tracking paths such as /sst or /data. Ad blockers often match those names, so pick something unique to your site.

Replace it with your path everywhere: the Worker route, the snippet, and, if applicable, the WAF rule.

Step 1: Deploy the Worker

Log in to the Cloudflare dashboard.

Go to Workers & Pages → Create application → Create Worker.

Choose the Hello World starter template.

‍Note: Do not pick Upload and deploy or Import a repository. Those expect a build pipeline and will reject a plain script.

Click Deploy to create the Worker with its sample code.

Once it's live, click Edit code.

Select all the sample code in the editor and delete it.Paste in the following code:

Logo of TAGGRS Server-side Tracking: a light blue circle with two blue angle brackets
export default {  
async fetch(request, env) {    
if (!env.
TAGGRS_HOST) {      
return new Response('Worker misconfigured: set
TAGGRS_HOST.',
{ status: 500 });    
}    
const url = new URL(request.url);    
const target = new URL(url.pathname.replace(/^\/[^/]+/, '') + url.search, `https://${env.
TAGGRS_HOST}`);    
const headers = new Headers(request.headers);    
headers.set('host', env.
TAGGRS_HOST);    
headers.set('x-forwarded-proto', 'https');    
return fetch(target, {      
method: request.method,      
headers,      
body: ['GET', 'HEAD'].includes(request.method) ? undefined : request.body,      
redirect: 'manual',    
});  
},};

This Worker reads your tracking host from one environment variable. It strips the first path segment and forwards the rest, including the query string. A request to yourdomain.com/metrics/abc1234567.js becomes /abc1234567.js on your tracking host. 

You do not need to edit Product ID or path values inside this code. The host comes from the variable in Step 2. The path comes from the route in Step 3.

Click Deploy again to publish your version.

Step 2: Set the tracking host

Open your Worker → Settings → Variables and Secrets → Add variable, and add one variable:

  • Name: TAGGRS_HOST
  • Value: your tracking hostname only, for example sst.yourdomain.com. Do not include https://.

Save. If Cloudflare asks you to redeploy for the variable to apply, do so.

Step 3: Add the route

Open your Worker's Domains / Triggers tab and add a route for your domain.

‍Important: do not use yourdomain.com/*. That runs the Worker on every request to your site and counts all of them against Cloudflare Workers limits. Bind only your tracking path.

Add this route, replacing metrics with your path:yourdomain.com/metrics/*

If your site also runs on www, add the same pattern for www:www.yourdomain.com/metrics/*

The route field accepts one pattern at a time. Click Add route after each one.

Step 4: Confirm proxied DNS

Go to DNS → Records and confirm the records that serve your site show the orange cloud (Proxied).

Workers only run on proxied traffic. If your site is served from www but the www record is DNS only (grey cloud), the Worker will not apply there.

Step 5: Allow GTM Preview through Cloudflare

Because this setup requires the Cloudflare proxy (orange cloud), Cloudflare security features can block GTM Preview. Preview reloads your tracking script with gtm_debug, gtm_preview, and gtm_auth on the query string. Bot Fight Mode and the WAF often treat those requests as automated traffic, so Preview fails even though live tracking works.

The solution to this is to add a custom WAF rule that skips bot checks for Preview requests under your tracking path.

Go to Security → Security rules (or Security → WAF → Custom rules) → Create rule.

Name it Allow TAGGRS GTM Preview.

‍
Use this expression, replacing metrics with your path:

Logo of TAGGRS Server-side Tracking: a light blue circle with two blue angle brackets
(starts_with(http.request.uri.path, "/metrics/")) and (http.request.uri.query contains "gtm_debug" or
http.request.uri.query contains "gtm_preview" or
http.request.uri.query contains "gtm_auth")

Set the action to Skip.

In the skip list, select Super Bot Fight Mode. If Bot Fight Mode appears as an option, select that too.

Deploy the rule.

On Cloudflare's Free plan, Bot Fight Mode cannot be skipped with a WAF rule. If Preview still fails on Free, turn Bot Fight Mode off for the zone or upgrade.

If collect calls or the loader itself return 403 with a cf-mitigated header, skip Super Bot Fight Mode for the whole /metrics/ path instead of only the Preview query parameters.

Step 6: Update your tracking snippet

Keep the standard TAGGRS snippet. Change only the script and noscript paths so they include your tracking path and keep the Product ID filename.

Before:

Logo of TAGGRS Server-side Tracking: a light blue circle with two blue angle brackets
j.src = 'https://sst.taggrs.io/' + i + '.js';

After:

Logo of TAGGRS Server-side Tracking: a light blue circle with two blue angle brackets
j.src = '/metrics/' + i + '.js';

If you use the noscript fallback in the body, update it the same way:

Before:

Logo of TAGGRS Server-side Tracking: a light blue circle with two blue angle brackets
<iframe src="https://sst.taggrs.io/abc1234567.html" ...></iframe>

After:

Logo of TAGGRS Server-side Tracking: a light blue circle with two blue angle brackets
<iframe src="/metrics/abc1234567.html" ...></iframe>

The filename must stay {Product ID}.js. If you rename the file, the script cannot derive the public path and tracking falls back to the old tracking host.

You do not add a snippet variable. The loader reads its own script URL and sends events to /metrics/{Product ID} and assets to /metrics/dfp.min.js, /metrics/ns.html, and the rest.

Step 7: Verify that everything is working

Run through these four checks in order:1. Loader responds. Open https://yourdomain.com/metrics/YOUR_PRODUCT_ID.js. You should get HTTP 200 and JavaScript, not a 404.
2. Script loads first-party. Open your site, open DevTools → Network, reload, and confirm the tracking script loads from your domain under /metrics/{Product ID}.js.
3. Collect calls stay on the same path. Confirm collect traffic goes to /metrics/{Product ID} on your domain, not to the old tracking subdomain.
4. Data arrives. Check GA4 Realtime or your analytics dashboard and confirm events after the switch.
5. Cookie lifespan is fixed (iOS). In Safari, open your site, then DevTools → Storage, and find your tracking identity cookie. Confirm its expiry shows the full intended lifespan (often a year or more) instead of roughly 7 days.
6. Preview works. Open GTM Preview as described in Test your Server-side Tracking configuration. If Preview is blocked, go back to Step 6.

Cost and limits

For most sites, this can run on Cloudflare's free Workers plan. The free tier allows 100,000 Worker requests per day, resetting at midnight UTC.

Because the Worker is bound only to your tracking path, normal pages, images, and CSS do not count. What counts is each TAGGRS request under that path: the loader, a few supporting assets, and each collect or tag call.

If you approach the free daily limit, Cloudflare's paid Workers plan removes the hard daily cap. Check current figures on Cloudflare's Workers pricing page.

FAQ

Do I need to change anything in my TAGGRS dashboard?
No change is required for the path mapping itself. Your product, container, and tags stay as they are. If you use the Service Worker experiment, add your website hostname as a custom or additional domain so those requests resolve to the right product.

Will this affect my normal website pages?
No. The Worker only runs on the route you add, for example yourdomain.com/metrics/*. Everything else goes to your site as before.

Does this work if my site is not on Cloudflare?
This guide is for Cloudflare. The same strip-forward pattern works on other reverse proxies (Nginx, Vercel rewrites, edge functions). Use the same public path and the same snippet. If you are not using a reverse proxy, the standard domain routing setup via a tracking subdomain remains fully supported.

I already proxy these paths on my own server. Should I do both?
No. Pick one method only. Running the Cloudflare Worker and another proxy for the same path can cause double-forwarding.

Will this recover 100% of blocked tracking?
No setup can promise that. Same-origin loading removes hostname-based blocking, which is a common source of loss, but some browsers apply additional tracking-prevention. If you want to push measurability further, combine this with the Enhanced Tracking Script.

How do I change the path later?
Change the Worker route, the snippet src, and the WAF expression. Nothing else. The loader re-derives the new path from its own URL on the next page load.

Useful resources

icon of a white thunder used by TAGGRS to visually introduce Server-side Tracking
Start for free with Server-side Tracking
icon of a white upward arrow
White silhouette of a person used as icon for the support call to action
Get expert support
icon of a white upward arrow
Previous
Spectacle Server-side Tracking
Next
Shopify Data Layer
DOCUMENTATION V1.4
Copyright © 2026 TAGGRS. All right reserved.