DEV Community

fejc
fejc

Posted on

A UTM click is not a visit: the sensor I added to fix my analytics was lying too

Three days ago I published a post arguing that my launch metrics were mostly machines. Forty-six views, zero sales, and — after I put UTM parameters on the only two links I had published — exactly two clicks that I could attribute to anything I wrote.

The post ended with advice I was pleased with: when two stories explain the same data equally well, stop writing the third version of the argument and go add a sensor.

The sensor is now installed. It has been running across thirteen links. And it turns out it was lying to me in a different direction, which I would not have noticed if I had trusted it the way I was planning to.

Where the numbers are now

24 Oct 27 Oct
Views, total 46 88
Attributable UTM clicks 2 16
Sales 0 0

Fourteen new clicks in three days, after five days of two. By the standard I had just finished defending in public, that is the good number — the one that means real people, as opposed to the view count, which means nothing.

Seven of them came from the post itself. Four came from a longer technical article I published on another platform. Four more came from an earlier post here. One came from an older piece.

So: evidence of readers, finally. I had a tidy story ready about which channel works.

Then I checked the other end of the links.

Two clicks, zero views, two days

Here is the case that broke it, and it is as small as a case can get.

Two of those clicks point at one specific product page — a risk register template. One article links there, and nothing else does anywhere. The clicks are logged. The click count is two.

That product page has had zero views since launch. Including after both of them.

Two days after the first click was recorded, the destination of that click had still never been viewed by anyone.

That is not a subtle discrepancy. Those two counters are supposed to be describing the same event from two angles: somebody clicked a link, somebody arrived on a page. One of them is wrong, and it is not hard to work out which, because a page view is the thing that requires a browser to actually load the page.

I spent a while trying to make it lag. It doesn't work. Six hours of reporting delay I would have believed. Two days, on a dashboard that updates the view count on other products the same day, I don't. And the other direction — the page was viewed but the view wasn't counted — would have to be a bug that fires only on the one product nobody has visited.

Before going further I checked that the zero was a real zero and not a filter that wasn't applying, because those two look identical. I unticked every product and confirmed the total fell to zero. I ticked the one I cared about: still zero. Then I added a second product whose number I already knew, and it came back at exactly that number. The instrument works, and the zero is a zero.

What fits

The explanation that fits everything I can see: a good share of those clicks are link-preview crawlers, not readers.

Three signals, and it's the combination that matters rather than any one of them:

They arrive in the first couple of hours after publishing, and then stop dead. Two clicks in the first two hours, and zero in the nineteen hours after that. Real readership on a platform with a feed decays; it doesn't terminate. A publish-time spike that goes to exactly zero is the shape of something that fetched the page once when it was notified about it.

They don't produce a page view at the destination. Which is what you would expect from something that resolves a URL to generate a preview card and never renders the page.

And they arrive in a shape that readers don't make. This is the one that convinced me. In the last eighteen hours I gained four clicks, from two different articles, two each — and in both cases both links in the article went up by exactly one, at the same time. Read that as people and you need two readers per post, each picking a different one of the two available links, never the same one twice, independently, in both posts. Read it as one thing fetching every link on a page once and it needs no coincidence at all.

Meanwhile the view count keeps climbing without any of it: eighty-eight now, up seventeen in those same eighteen hours, and one country that didn't appear in my breakdown at all three days ago is now twenty-four of the eighty-eight.

I want to be careful here, because the whole point of the previous post was about not doing this. I can't prove any individual click was a crawler. What I can say is stronger than a preference and weaker than a proof: I have counters that disagree, and the disagreement is the finding. The click number alone was unfalsifiable in exactly the way the view number had been. It took a second counter, pointing at the same event from the other side, to make either of them mean anything.

And then I found a third counter I already had

I wrote all of the above believing I had two counters: clicks on my links, and views on my product pages. I was wrong about that too, and the way I found out is embarrassing enough to be worth writing down.

The platform I publish on has an analytics page. I had never opened it.

It says the previous post has been read fifty-one times. Not estimated, not inferred from a click — read, by its own count, with an average read time of four and a half minutes for the readers it can identify. Four and a half minutes is not a crawler. A crawler does not stay.

So the reach number I had spent a week triangulating from clicks was sitting one menu item away, and it changes the arithmetic completely.

What I assumed What the third counter says
People who read the post "a few hundred" 51
Clicks on its two links 7 7
Click-through "reasonable" 13.7%

Thirteen per cent is not reasonable. Thirteen per cent is very good, and it moves the diagnosis somewhere I wasn't looking. Fifty-one people read a post about my own failure and one in seven of them clicked through. Whatever is broken in this funnel, it is not the top of it, and I have spent a week measuring the top of it.

It also gave me the one clean reading in the whole dataset. That post's click count stopped moving in the same window its reader count stopped moving — frozen at seven and fifty-one together. Two independent counters agreeing that nobody is reading it any more is the only thing here I'd call a measurement rather than an argument. Everything that's still moving is moving on one counter alone.

And notice what had just happened to my own case. I published a post saying one sensor is not instrumentation, while a third sensor sat unopened in a dashboard I owned. I was not short of data. I was short of the habit of going to look for the counter that could contradict me — which is, word for word, the thing I was lecturing everybody else about.

So the advice I gave three days ago was half right

The half that stands: a link published without parameters is a measurement that can no longer be taken, and ninety seconds of instrumentation buys you the entire question.

The half that was wrong, and this is the part I'd change: one sensor is not instrumentation. A single counter can only ever confirm itself. I replaced a number I couldn't trust with a number I couldn't check, and I was two days from making channel decisions on it.

The fix is cheap and I should have seen it, because it is the same thing I do for a living. I plan data migrations. Nobody signs off a migration because the load job reported success — you reconcile the target against the source, row count against row count, and the differences are where the truth is. A click counter and a destination page-view counter are a source and a target. The number that tells you something is the gap between them.

The thing I wanted to do and didn't

There is a confession in here that I think is the most useful part for anyone at the same stage.

Once I understood that the click counter might be counting crawlers, the obvious next move was to click my own links. Open the link, watch whether the click registers, watch whether the page view registers, and settle the mechanism in about forty seconds.

I didn't, and the reason is the whole problem with being this small: I have sixteen data points. One deliberate click from me is six per cent of my entire dataset, permanently, with no way to subtract it later. The test that would have told me how the instrument works would have damaged the only thing the instrument is measuring.

That trade doesn't exist at scale and it is brutal at n=16. If you are instrumenting something with almost no traffic, decide before you start which of your own actions you are allowed to take, because every one of them is a measurable fraction of your results.

The comments that reframed all of it

The previous post got six comments, which is six more than anything else I have published, and two of the people in that thread were worth more than the post.

One reader pointed out that I should look for per-view timestamps to separate crawlers from people. My store doesn't expose them — views are aggregated by day — so I couldn't do it directly. The concentrated burst from a single country did the same job by accident, so he was right about the method even where the data wasn't there.

The other one took the whole thing apart, correctly. Paraphrasing: this is not a conversion problem and it is not really a measurement problem either. It's a reach problem. Below roughly a hundred real humans on the page, changing the product teaches you nothing, because you don't have enough signal to detect any effect you might have.

That is the sentence that stopped me redesigning things. I had a list: adjust the price, rewrite the page, redo the screenshots. With sixteen clicks of which some unknown number are machines, every one of those experiments would have returned noise, and I would have interpreted the noise. A week of careful measurement produced one defensible instruction, and it was go get traffic, stop editing the shop.

Then I replied with my numbers, and he came back with the piece I didn't have: a test for a visit that I can actually apply. Count a click as a visit only if it does one of three things — scrolls, stays about fifteen seconds, or reaches a second page. And discard anything that arrives in the first couple of hours after you publish.

I had got to that second rule on my own, from the shape of my own data, about a day before he wrote it down. Two people looking at different evidence and landing on the same cutoff is as close to a replication as a project this size is going to get.

And his three-part test is, I notice, more or less what the read-time number in my own dashboard had been measuring for me the whole time.

Five rules, in the order they would have helped

Instrument before publishing. Still the highest-return ninety seconds available. Unchanged from last time.

Open the dashboards you already have before you build a new one. This is the rule I most needed and it would have cost me nothing. I spent a week inferring a reach number from clicks while the platform was counting readers for me, with read times attached. Before you instrument anything, go and find out what every tool you already use is already counting.

Then add the sensor that can contradict the first one. A click counter plus a destination view counter. A source count plus a target count. If you only have one number, you don't have a measurement, you have an opinion with a dashboard behind it — which is what I accused my view count of being, while making the same mistake one layer up.

Prove a zero before you build on it. A filter returning zero and a filter that isn't applying look exactly the same. Add something whose number you already know; if that comes back right, the zero is real.

Define a visit before you count one, and know your n before you design an experiment. A click is a floor: it counts if it scrolls, stays about fifteen seconds, or reaches a second page. And at sixteen data points you are not testing a price — you are not testing anything, including, awkwardly, with your own clicks.

Still zero sales, for the record. But I now have three numbers that disagree in ways I understand, and one pair that agrees, which is a considerably better position than one number that agreed with whatever I wanted.


I build these as a delivery manager on cloud and data migrations. The weekly status report template is free, pay what you want including zero: the status report template

The full kit, 12 templates and 50 prompts, is here if it's useful.

If you've instrumented something small: what was the first counter you found out was lying to you? I'm collecting them.

Top comments (2)

Collapse
 
alexshev profile image
Alex Shev •

The disagreement between counters is the valuable result, because it turns a persuasive dashboard into a falsifiable system. I would keep a small reconciliation table keyed by link and time window, with expected browser-side events and known bot signatures, so future changes can distinguish instrument drift from a real audience change.

Collapse
 
robertpaschal profile image
Odinaka Robert Nnamani •

three counters, three stories. which one do you trust when they disagree?