The Bing pixel that said YOUR_VALUE_HERE
Quick Take
A six-month-old Shopify + Stape Pro stack I audited last week was firing placeholder text at Microsoft Ads for three conversion goals. The literal string YOUR_VALUE_HERE. Untouched since the snippet was pasted in. That was finding number four. There were seven more, including a Meta CAPI access token sitting in plaintext in GTM version history that anyone with read access could lift.
None of it was on fire. The store was making money. PMax was running. Dashboards looked tidy.
This is what an inherited tracking stack looks like after six months of drift. Here is the full punch list, and the structural reason agencies miss it.
The store had been running this stack for six months
I gave myself one afternoon to audit a six-month-old Shopify tracking stack. The store was paying an agency. They were paying for Stape Pro. They were running real PMax spend across Google, Meta, and Bing. From a distance the setup looked clean.
The first thing I found, forty seconds in, was a Meta Conversions API access token hardcoded in plaintext inside a GTM tag from 2024. Still the live token. Still powering every server-side Meta purchase event in production. Sitting in version history that anyone with read access to the workspace could scroll back to and copy.
The fourth thing I found was three Microsoft Ads conversion tags with the literal string YOUR_VALUE_HERE in the conversion-action ID fields. For six months, every conversion the store had sent to Bing carried placeholder text from the snippet documentation. Untouched. All firing. All wrong.
The PMax was running. The campaigns were “optimizing.” Whatever Bing thought the brand was selling, it wasn’t.
This is a Shopify baby and parenting brand. Real revenue, real ad spend. The kind of operation where the tracking layer is supposed to be the boring part. They had inherited the GTM build from a previous agency relationship and had been told everything was in good shape.
I gave myself an afternoon to look. Web container, server container, Shopify theme, Stape dashboard, GA4, Events Manager, Microsoft Ads. The pass any senior operator should do on a stack they did not personally build.
Here is what was in there, in order of how angry it made me.
Two GA4 properties were receiving production data
The real one, the one the marketing team was reporting on, and a phantom property called G-23179768 that nobody on the team recognized. Both collecting pageviews. Both collecting purchases. The real property was undercounting because every event was being split. The phantom was a black hole nobody was looking at.
I asked who set it up. Nobody knew. It had been collecting events for months.
The fix was in a place you would not find unless you went looking. Shopify admin → Sales channels → Google & YouTube → Settings → Data sharing and tag management → Additional conversion measurement settings → Google tags. Six menus deep. The phantom GA4 was bound there as a “manually added” tag with a trash-can icon next to it. Click trash. Save. Phantom property stops getting fed.
The Custom Loader was paid for and idle
Stape Pro tier with a Custom Loader subdomain configured at load.gtm.[brand].com. DNS pointed at the right place. SSL valid. Hitting the URL directly returned a 200 with a real gtm.js payload. The custom loader had been live for ten days.
Stape Analytics showed 0% adblock recovery over those ten days.
The reason was simple. theme.liquid was still loading the container from www.googletagmanager.com directly. uBlock Origin and the standard blocklists caught it on every visit and that was the end of GTM for anyone with an adblocker. The entire reason to pay for Stape Pro is so the loader script comes from your own domain and adblockers stop blocking it. The store was paying for the upgrade and not using it.
The fix is a find-and-replace, but in more places than you would expect. theme.liquid has the GTM bootstrap snippet’s j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl; line plus the <noscript> iframe src attribute right below it. Both need swapping. Then search the rest of the theme for googletagmanager.com. If the store runs PageFly, you will find at least one more hit in snippets/pagefly-main-js.liquid. If they run Klaviyo or Judge.me with their own injected scripts, those snippets too.
One gotcha that wasted ten minutes of my afternoon. The Shopify theme code editor does not auto-save. Find/Replace updates the in-memory buffer for every matched file. It does not write any of them to disk. If you Replace All across six files and then click away, every change vanishes. You have to open each modified file individually and hit Ctrl+S. The dirty-file indicator (a small dot on the filename in the sidebar) tells you which still need saving.
Shopify’s Google channel was duplicate-loading the container
This one I had to look at twice. View source on the storefront. Search for the store’s GTM- container ID. It appeared three times. Once at the top of <head> from theme.liquid. Twice at the bottom of <body> from somewhere else.
The somewhere else was the Shopify Google & YouTube sales channel. When the store connected Merchant Center plus Google Ads through it, the channel auto-injected four gtag scripts at the bottom of every storefront page. An AW- conversion ID. A GT- unified tag. The phantom GA4 from item one. And the store’s own GTM container, which was already loading from the theme.
So the container was loading twice on every page. Every dataLayer event was firing into two instances. Conversion tags configured inside the container were eligible to fire twice. Whether they actually did depended on dedup logic and event_id presence, which on this store was inconsistent.
The fix is the same six-menu-deep panel as the phantom GA4 fix. Same “Google tags” list. The “Installed” tags are tied to the connected services and you cannot remove them without disconnecting Merchant Center or Google Ads. The “Manually added” tags have trash-can icons. Click trash on every manually-added entry that duplicates what your GTM container already fires. Specifically: any GTM- container ID that matches your web container, any GA4 measurement ID your GTM already sends to, and any GT- unified tag overlapping with sGTM-handled conversions.
After saving, the storefront should load the container exactly once. View source again to confirm.
The Facebook auto-setup from 2024 was still firing
Meta’s Conversions API auto-setup wizard tag suite from over a year ago was live in the container. Five web tags. One server tag. Eight orphan supporting variables. All firing in parallel with the newer Stape-based Meta CAPI build that the current agency had shipped.
So every purchase was being sent to Meta twice. Once by the legacy auto-setup, once by the proper server-side build. Meta deduplicates on event ID when both events have matching IDs. These did not. Six months of inflated purchase counts in Ads Manager.
The fix was deletion. Both containers. Tags, supporting variables, the connected triggers. Plus the two pre-existing orphan triggers I noticed while I was in there, both pointing at a .asp checkout URL pattern Shopify hasn’t used in over a decade. They were sitting there as confusion from a platform migration that probably happened five years before the current agency relationship.
The Microsoft Ads conversions were firing YOUR_VALUE_HERE
Covered at the top. Three tags. Six months. Bing campaigns optimizing toward noise.
The three constants holding the placeholder text were stored as variables with names like const - mads_purchase_conversion_action. A real human had pasted the template into GTM and never come back to fill in the conversion IDs. A real human had then published the workspace anyway. Six months later, still pasted, still firing.
The Meta CAPI access token was leaked in version history
The auto-setup wizard hardcodes the Meta CAPI access token as a plaintext tag parameter. Every time you publish the server container, that version is saved with the token embedded. Six months and dozens of versions later, the token is in dozens of places. Anyone with GTM read access on the container, now or at any future point, can browse version history and copy the token.
If the engineer who set this up leaves the company, you cannot rescind their access to that token without rotating it.
The rotation flow is well-documented but has a sequencing trap worth knowing about. Meta Events Manager → Pixel → Settings → Conversions API → Set up manually → Generate access token. Copy the new token. Switch to GTM server container. Find the Constant variable holding the token. Replace the value. Save. Publish a new server container version. Verify in Events Manager that events are still arriving and matching for at least an hour.
Do not immediately click “Revoke tokens” in System Users. That button is binary. It revokes every token issued to that system user, including the one you just generated. If you click it the same day you rotate, you will break the active tracking you just set up. Schedule the revoke for a coordinated double-generate rotation in a quiet window.
While I was in the server container I also updated the taggingServerUrls admin field, which was still showing the raw Cloud Run URL underneath even though the live custom subdomain had been provisioned for months. Mostly cosmetic, but it matters for Preview/debug mode to attach against the correct hostname.
Some good news, briefly
The Stape side of the build was not all broken. Safari ITP recovery was working. 45 percent of events were being recovered from tracking prevention. 51 percent of purchase events specifically. So the server container was doing its job for ITP, which is the harder of the two problems to solve.
That made the adblock zero even more frustrating. The hard problem was solved. The easy fix had been left undone for six months.
This isn’t an outlier. This is the average six-month-old setup.
I want to be careful here. The person who set this stack up was not bad at their job. They got 80% of it right on day one. The CAPI was wired through sGTM. The Custom Loader subdomain was provisioned. The container structure was reasonable. Whoever built it understood the stack.
Then they moved on. To a new account. A new client. A new sprint. Drift started accumulating from week two.
Shopify pushed an update to the Google sales channel. The theme got edited by a developer who didn’t know GTM was already in the page. A new conversion goal got added in Microsoft Ads and the snippet got pasted in without the ID. A token rotated and the old one stayed in version history. The second GA4 property got created during a test and never deleted.
Every Shopify store with a 12-month-old tracking stack has drift like this. I have audited enough of them to stop being surprised. The question is never whether the drift exists. The question is who gets paid to come back and find it.
Who actually touches the account
Here is the part nobody on the agency side wants to talk about out loud.
The senior who pitched you is not the senior on your account. The senior on your account today is fronting four to eight other accounts. They run the weekly call. They read the dashboard their analyst built. They forward the questions to a junior. The junior is the one in GTM. The junior is the one in Stape. The junior is the one who never opens version history because nobody told them version history is where the leaked token lives.
This is not a talent problem. The senior at the agency is good. I have worked alongside them. They were good when they were the one in the keyboard six years ago. They got promoted out of it. That is how agency career ladders work. The reward for being good at the work is no longer doing the work.
The question stops being “is my agency competent.” The question becomes who is the actual human inside my GTM container this week, and how many other containers are they in.
A senior strategist billing $300 an hour cannot spend an afternoon reading every tag in a client’s GTM container. The margin model breaks. So the afternoon does not happen. So the drift stays. This is structural, not a talent gap.
If your tracking stack is older than twelve months
You probably have at least three of these in your container right now. The legacy auto-setup tags. The phantom property somebody added during a sales channel install. The orphan triggers from a platform migration. The placeholder text that never got filled in. The paid-for adblock recovery that the theme is bypassing.
Four checks, in order, each under five minutes:
- View source on your storefront. Search for
googletagmanager.com. If you find it, your Custom Loader is configured and your theme is bypassing it. Search for yourGTM-container ID. If it appears more than once, the Shopify Google channel is duplicate-loading. - Open your GTM server container. Admin → Container Settings. If
taggingServerUrlsshows a.a.run.appURL, that field is stale. - Open your Meta CAPI server tag in GTM. Click the access token field. If you see a token string instead of a variable reference like
{{const - meta_capi_token}}, your token is leaked in version history. - List every GA4 property in your Google Analytics admin. If you have more than one with live traffic in the last seven days, you have a fork.
If you find one of these, there are probably six more. They travel in packs.
I wrote up the full architecture I use for this kind of pass at The Tracking Stack. Walk it yourself, or send it to whoever built your stack and ask them to walk it for you. Watch what they say when you get to the version history step.
If you want me to do the pass, hi@connercrowe.com. One afternoon, fixed price, written findings. I do not need access to your ad accounts to start. The container tells the story.
The store I audited is going to find this work regardless. The only variable is whether they find it before Q4 or after. Before Q4 means the holiday spend lands on a clean stack. After Q4 means Meta and Google spent the brand’s busiest quarter optimizing on duplicated conversions and a Bing pixel firing placeholder text.
If you have an agency and a “senior strategist” on the account, here is the one question worth asking on the next call.
When was the last time you, personally, opened the GTM container and read every tag?
The answer tells you who is actually on your account.
Keep going
If this hit, the next two pieces in the same universe:
- The Click Text Trigger Trap. The GTM bug that silently kills conversions when you change button copy.
- Nine GTM Tags in 90 Minutes. The same audit shape, 90 minutes of API tooling, nine new entities shipped.
Free PDF: The 25-page Tracking Stack. No email gate.
More reading
-
The inbox is a catalog surface, and most home brands waste it with a stock template
I built 5 Klaviyo flows and 21 hero emails on 7 custom room scenes for a $3,000-AOV furniture brand. At that price, the abandoned-checkout email is the cheapest revenue you own.
-
One hero shot loses the sale: the four product angles every furniture PDP needs
A single 3/4 hero shot leaves a furniture buyer guessing on depth, edge profile, and joinery. Here are the four white-background angles a PDP needs, and why the set is per-product.
Want a review like this on your account?
Want this kind of review
on your account?
Thirty minutes on the phone. Same person on the call as on the work. Walk out with a clear set of next steps.