“Other products” is a measurement defect, not a category: recovering product names from a SKU-only revenue report
A catch-all line on a performance dashboard turned out to contain an entire product launch, because one channel reported revenue by SKU and never by name. How the mapping was recovered, and why a residual bucket should document itself.
A product that had been selling for months had no row on the dashboard at all. Not a zero. No row. Its revenue was sitting inside a line called "Weitere Produkte" — other products — which I had been reading for weeks as a tidy little tail of odds and ends.
It was not a tail. It was two named products that the pipeline simply could not name.
The question that started it
The brand is in home and living, selling across its own shop, Amazon, OTTO and a marketplace or two, and the performance dashboard rolls all of that into one product view. The owner asked a reasonable question in passing: what actually is "other products"? A line item sitting there every day, in a bucket nobody had ever opened.
I expected sample sizes and discontinued SKUs. What I found was a reporting defect with a name that made it look like a category.
Why the names were missing
The direct shop is measured in Matomo, and Matomo reports ecommerce items through separate endpoints: one that lists items by SKU and one that lists them by name, each returning its own revenue and quantity. The pipeline pulled the SKU report, because SKU is the stable key across every other channel.
Then it resolved those SKUs to product names by joining on the digits in the SKU against the marketplace feeds, where names are present. Clever, and it worked for every product that also sells on a marketplace. A SKU that had only ever sold on the direct shop never appeared in any feed, so it never got a name, so it fell through to the catch-all.
That is the whole bug. The channel with the richest data about the brand's own customers was the one channel whose products could go unnamed, and the newest product — which launches on the own shop first, naturally — was the most likely to land in the bucket. The dashboard was least informative exactly where it mattered most.
A residual bucket is not a category. It is the part of your report that has not been built yet.
Recovering the mapping without asking anyone
The fix did not need a product manager or an export from the ERP. The two Matomo endpoints describe the same transactions from two angles, so the names were already in the system — just in a different table.
So: pull the daily SKU report and the daily name report across the full history, two hundred and six days of it, and join them on the pair (revenue, quantity) per day. If on a given day exactly one SKU and exactly one product name share the same revenue and the same unit count, that is almost certainly the same row seen twice. Twenty-one of twenty-two SKUs resolved to a unique name that way.
The twenty-second needed a human. One product sells in several sizes that get aggregated in the name report, so a single unit at one price inside a larger same-name total had to be reasoned about rather than joined. Ten minutes of looking, one annotated line in the mapping file, done. The sort of thing where the model does the two hundred days of arithmetic and I do the one ambiguous case — which is where the actual leverage lives.
The mapping is a small JSON file in the repo, read by the build step, with a graceful fallback to the old behaviour if the file goes missing. It is in the workflow's push triggers too, so editing the map rebuilds the dashboard on its own. That matters more than it sounds: a fix that requires a human to remember a second step is a fix with a half-life.
Make the residual self-documenting
Here is the part I would keep if I kept nothing else. Unknown SKUs still fall through to "other products". I did not try to make the bucket impossible.
What changed is that the row now carries the list of SKUs inside it. So the bucket has stopped being an admission of defeat and become an instruction: these are the identifiers I could not name, go and add them to the map. The maintenance rule is one line — when a new SKU shows revenue under "other products", add it to the file and push.
Google does the same thing deliberately in GA4, incidentally, and is open about it. The (other) row appears when a table exceeds its row limit, and the guidance is explicit that any dimension with more than about five hundred values should be treated as high-cardinality. The difference is that Google tells you why its bucket exists. Most internal dashboards do not, because nobody wrote the bucket on purpose — it is the default branch of a lookup that someone hoped would always hit.
The habit worth stealing
Every report has a catch-all somewhere. Direct traffic. Other. Unassigned. Not set. Uncategorised. Each one is a lookup that failed, dressed up as a finding, and they are all quietly reassuring because a small number in a vague row looks like rounding error rather than a hole.
So the habit is this: for every catch-all in a report you rely on, be able to say in one sentence what lands there, why, and what would make it shrink. If you cannot, open it. I have found a dashboard lying by omission and a channel filter quietly breaking a ROAS figure this way, and in both cases the number that was wrong looked far too small to be interesting.
The one on this dashboard was small, too. It was also an entire product launch.
Open the bucket. Something is in there.
Sources & further reading
External
Matomo Reporting API reference — the Goals module's getItemsSku, getItemsName and getItemsCategory ecommerce item reports
Manually tracking ecommerce actions in Matomo (Matomo FAQ)
About the (other) row (Google Analytics Help)
Cardinality in GA4 (Google Analytics Help)
Related posts
The analytics dashboard lying by omission
A channel filter broke our ROAS by attributing ad spend
The client dashboard that reports enquiry value, not revenue
The death of generic AI: why deep domain expertise is the only real leverage left