- 1PD Ops Club
- Posts
- Your COGS field is empty
Your COGS field is empty
That has got nothing to do with tracking, but it has got everything to do with optimization
Hellooo,
I sat in on three calls with a US Shopify Plus brand over the last few weeks. And I want to tell you what happened, because it has nothing to do with what you think it has to do with.
This brand had everything.
Server-side tracking tool. Attribution tool. Email platform. SMS platform. Product analytics platform. ERP. Returns app. Consent app.
Eight tools. A stack that would make most ecom teams jealous.
But the problem was they could not send a single signal that actually mattered to them.
Here's what they wanted
Three things. All reasonable.
One: stop telling Meta "purchase" and start telling it as "profitable purchase."
Two: stop acquiring customers who return everything.
Three: see one unified customer profile instead of six half-profiles.
Every one of these is a solved problem technically. Every one of them was blocked.
Not by the tools, But By an empty field
We opened their Shopify product page on the call. Scrolled to the cost per item field.
We saw the blank.
Nobody had ever filled it in. The real COGS lived in NetSuite, but NetSuite only registers margin after payments are applied, which is days after the order. And their actual cost per unit swings with tariffs and PO batches anyway.
So here's the situation: a brand that desperately wants Meta to optimize for profit, sitting on an ERP full of profit data, and there is no path from that data to the ad platform in a timeframe the algorithm can use.
You cannot send a signal your business has not written down somewhere a system can read it.
That's it. That's the whole thing.
Their fix, by the way, was not heroic. Their ops lead pulled the lowest wholesale tier price from their B2B catalog and proposed using it as a baseline cost. Not exact. Directionally right. Automate it across the catalog, and suddenly a "high margin purchase" event exists where nothing existed before.
Ninety percent right and flowing beats one hundred percent right and stuck in NetSuite.
Then we got to returns
Returns are creeping up month over month. And he asked the obvious question: can you tell Meta to stop finding people who return things?
We opened Shopify orders. Filtered by return status. No tags. No flags. Nothing marking a returned order.
Because their returns app owns that data. Shopify never gets told.
So the return event that everyone assumes is sitting in Shopify waiting to be sent?
It does not exist. It lives inside a third-party app that nobody thought to connect, and the fix was a webhook conversation with the returns vendor that had never happened in years of running the store.
And here is the part almost nobody gets right
Even once you have return data, you cannot send it as a conversion event.
Think about the timing.
A purchase fires the second it happens. Ad platforms want it immediately. That's the deal.
A return happens three weeks later. There is no way to retroactively tell Meta "remember that purchase event? Bad one."
So returns are not a signal. Returns are an audience.
You collect the profiles of people who returned, build a cohort, push it to your ad platforms, and set it to permanent exclusion. Then you seed lookalikes from the people who kept the product.
Marketers who try to force returns through the event layer get nothing and conclude it doesn't work.
The third one: everyone had a profile, nobody had the customer
Their product analytics tool showed beautiful user journeys - pages, clicks, videos watched, UTMs, city, device.
User ID field: blank.
It only populated when someone logged in or placed an order. Everyone before that was a ghost with a rich behavioural history and no name.
Meanwhile Shopify had its own ID. The ERP had another. The email tool had another. Four systems, four identities, one actual human, zero stitching.
The unified customer profile everyone assumes they have is usually four disconnected profiles wearing a trench coat.
Looks like three separate problems, but really it is just one
None of these tools own identity. They each hold one fragment and hand it downstream. So there is no layer where cost data, return data, browsing behaviour, and CRM data can meet the same person.
That layer is what CustomerLabs is.
Concretely, for this stack:
A first-party domain cookie assigned server-side, not browser-side, so it survives ad blockers, ITP, and AI browsers, because it comes from your DNS, not a third party's script
A profile that starts on the anonymous first visit and keeps appending behaviour, so when they reveal themselves on day 200 the entire journey is already attached
Shopify's customer events sandbox for checkout, so checkout extensibility isn't a black hole
Profit-tier and category purchase events built off a COGS field, sent to Meta, Google, TikTok as distinct signals, not one generic Purchase
Returner cohorts pushed as permanent exclusion audiences, with lookalikes seeded from keepers
Webhook destinations for tools we don't natively integrate with, so an SMS platform or a returns app can still be part of the loop
Consent state pulled in, so profiles that declined simply don't get activated downstream
One identity layer. Every tool downstream finally talking about the same person.
The uncomfortable question
Go open a product in your Shopify admin right now. Scroll to cost per item.
Is there a number in it?
If not, no amount of CAPI, attribution software, or algorithm whispering is going to make your ad platform optimize for profit. It cannot optimize for something you have not written down.
Start there. Then come talk to us about the rest.
Book a 1:1, we'll audit which signals you're structurally unable to send Or start the 14-day trial and see your own event accuracy first

Reply