An ecommerce client is already pushing ecommerce data into their data layer, but without an event attached to it. No event means we have no way of knowing when the data arrives, and if we do not know when it arrives we cannot pass it on. Small problem. It is only small if you can edit the code.
We cannot. We do not have visibility into every occurrence in their codebase, and honestly we should not - it is their application. So my job this morning was not to fix it. It was to describe the fix precisely enough that somebody who does not work for me, and who will not stop to ask what I am trying to achieve, can carry it out correctly on the first attempt.
What I actually sent
Search for this combination:
dataLayer.push({
'ecommerce': {
Replace it with this:
dataLayer.push({
'event': 'ecomPush',
'ecommerce': {
That is an event slipped into the pushes that already carry ecommerce data, which should catch every occurrence without anyone needing to know what we intend to do with them. The event name itself is arbitrary as long as it matches what we configure at our end, and configuring it is our problem, not theirs.
Where it breaks
There is one case where find-and-replace is not enough, and I wrote it into the mail rather than hoping it did not apply.
If they have pushes that send something else before the ecommerce payload, the block does not match my search pattern and gets missed. The correct method is to find every occurrence of dataLayer.push({, look inside each block for 'ecommerce', and add the event line if it is there. Position within the block does not matter, as long as it is the same push. If it goes last, drop the trailing comma.
That is more work, and it needs whoever does it to think rather than run replace-all. I do not know what their code looks like, so I do not know whether this is a real problem or a theoretical one.
Why a recipe and not a specification
I could have written “please fire a dataLayer event whenever ecommerce data is pushed” and left the implementation to them. It would have been shorter and it would have looked more respectful of their expertise.
It also would have been worse, and the reason is not about their ability. It is that a specification has to be interpreted, and interpretation requires context I have and they do not. They do not know which downstream tool is listening, or that the event has to be inside the same push rather than adjacent to it, or that a near-miss produces data that looks fine and is wrong. A recipe carries all of that silently. They execute the steps and the context comes along for free.
The caveat matters as much as the steps, though. If you send an instruction that looks watertight, it gets executed as if it were watertight, and then everyone stares at odd-looking numbers a month later. Write down where it can break and you often get a reply saying “we do have some of those” - at which point the mail has done its job before anyone touched the code.
There is a real limit to this, and I want to be fair about it. A recipe is right when the change is ours and they are executing it for us. It is wrong when the thing being built is theirs to own afterwards, because then a recipe robs them of the reasoning and you get a codebase full of instructions nobody on the owning team understands. The test I use is: who will be looking at this line in a year, and will they need to know why it is there? If the answer is their team, write the specification and accept the slower conversation. If the answer is us, send the recipe.
For a tracking event that only our tooling listens to, it is clearly us. So it is a recipe, and I am not really torn about it.
Do you know what the failure actually looks like here? Nothing crashes. The site works, checkout works, the customer notices nothing at all. The only symptom is missing rows in a report nobody opens until somebody needs it. So the handoff cannot end at “they implemented it” - somebody has to place an order afterwards and watch the event arrive, and that somebody should be us, because we are the ones who know what correct looks like.
Regarding the timing of all this: it is a strange week to be writing about comma placement in a dataLayer call, given what is happening outside. But the orders still need measuring, and possibly more than usual right now.
If you hand tracking work to developers you do not manage - do you send them a pattern to replace, or a description of the outcome and let them solve it? I have gone back and forth on it, and I am fairly settled on the recipe now, though I am aware of how it reads.