Skip to content

How I'm testing with Nischler whether pages about cabinet sizes get Google traffic before there are any products. Demand check, parser and stop rules.

JP 8 min read

A tall cabinet in an online shop, listed as "approx. 80 x 40 x 190 cm". Is it 40 cm deep or 40 cm wide? For a tall cabinet you can make a decent guess. For a sideboard listed as "120 x 40 x 80" it gets harder, and if you're trying to fill a 30 cm gap next to the washing machine, a wrong guess means sending the thing back.

That's what I'm building Nischler for. You enter the size of your niche and see only cabinets that actually fit, from many shops at once. It's German, because the shops and the searches I'm going after are German. Shops usually filter by a handful of width steps and almost never by depth. Google's results for "schrank 30 cm tief" (cabinet 30 cm deep) are full of marketplace category pages and product pages that mix up width and depth.

Nischler is an experiment in two stages. The product search is built but not online yet. Right now Nischler runs as a beta without products: 30 guide pages for the most common sizes and a niche calculator. The first question is only whether Google sends anyone to pages like these. If it does, product data and affiliate accounts come next, along with the second question: do visitors click through to a shop? Affiliate commission is how Nischler would pay for itself. I wrote down when I'd stop before the first page went online.

Demand first, code second

Before I knew anything about parsing dimensions, I wanted to know whether anyone searches like this. Google's Keyword Planner gives volumes, but it needs an Ads account and only shows rough ranges without a running campaign. There's a cheaper signal that works right away: Google Autocomplete. Google only suggests queries people actually type. If "hochschrank 30 cm" gets completed to "hochschrank 30 cm breit 60 cm tief" (30 cm wide, 60 cm deep), someone is searching for exactly that.

The script is short: six cabinet types times thirteen sizes, one request per seed, a bit over a second between requests.

ts
const seeds = TYPES.flatMap((t) => SEED_VALUES.map((v) => `${t} ${v} cm`));
for (const seed of seeds) {
	const url = `https://suggestqueries.google.com/complete/search?client=firefox&hl=de&gl=de&q=${encodeURIComponent(seed)}`;
	const [, suggestions] = await (await fetch(url)).json();
	results[seed] = suggestions;
	await sleep(1200);
}

All 78 seeds came back with size suggestions, from shoe cabinets at 15 cm to wardrobes at 180 cm. Of the 746 distinct suggestions, 131 combine several axes, like "badschrank 20 cm tief 30 cm breit" (bathroom cabinet, 20 deep, 30 wide) or "schrank 60 cm breit 40 cm tief 200 cm hoch". A shop filter with a width dropdown can't answer those. A size search can.

The probe doesn't tell you how often people search, though. The list of 336 keywords for the Keyword Planner is ready, and I'll add the number once I have it.

Which number is the depth?

The hard part of the product search is the product data. Affiliate networks deliver shop feeds as CSV, and the dimensions come in every shape you can think of:

  • dedicated columns for width, height and depth (rare)
  • B/H/T: 80/190/40 cm or HxBxT 1900x800x400 mm, axes and numbers in the same order (B, H, T are the German letters for width, height, depth)
  • Maße (cm): B: 320 H: 90 T: 215, with the unit somewhere else entirely
  • 17 cm tief in the middle of a sentence
  • ca. 80 x 40 x 190 cm with no axis labels at all

A deterministic parser handles everything that's labelled. It reads the axis sequence (HxBxT) and maps the numbers to it, it picks up a unit even when it's given once for all values, and it guesses the unit from magnitude when there is none (for furniture, 1900 is more likely mm than cm). Then comes a plausibility check. A cabinet that's 150 cm deep almost certainly has its axes swapped, so it stays out of the search.

That leaves the unlabelled triple. The obvious heuristic is "largest number is the height, smallest is the depth". For wardrobes and tall cabinets that's usually right. For sideboards, lowboards and chests of drawers the largest number is the width. A heuristic that sometimes swaps width and depth is exactly the mistake Nischler is supposed to fix, so the code never guesses here.

Instead, the product goes to Claude with title, category and description and a fixed response schema:

ts
const ExtractedDimensions = z.object({
	width_cm: z.number().nullable(),
	height_cm: z.number().nullable(),
	depth_cm: z.number().nullable(),
	outer_dimensions: z.boolean(), // false when only inner or compartment sizes are given
	confidence: z.enum(['high', 'medium', 'low']),
	reasoning: z.string()
});

The result only becomes searchable if all three axes are there, they're outer dimensions and the confidence is at least medium. Everything else stays invisible and isn't sent again. I'd rather show one cabinet too few than one that doesn't fit the gap. Products resolved this way carry a "dimensions assigned by AI" badge, so nobody trusts them blindly.

It's cheap because the model only sees what's left over. The parser takes everything labelled, and an LLM result survives every re-import as long as title and description stay the same. With Opus at low effort I expect about one cent per unresolved product. That's an estimate. I'll only know the real share of unlabelled sizes once the real feeds are in.

"30 cm deep" means 27 to 30.4 cm

Someone searching for a cabinet 30 cm deep doesn't want one that's 12 cm deep, even though it technically fits. So every axis in Nischler is a range in millimetres. The search for "30 cm deep" takes everything from 27 cm to 30.4 cm. The extra 4 mm catch shops that round 29.6 cm up to 30. From 100 cm up the margin is 5 cm, because big cabinets are rarely sold to the centimetre.

Results are sorted by fit: first the cabinet that leaves the smallest gap, summed over every bounded axis.

sql
ORDER BY (? - width_mm) + (? - depth_mm) ASC, price_cents IS NULL, price_cents ASC

The guide pages also explain what tends to go wrong when you measure. My favourite detail is tilt clearance. A cabinet that's assembled lying down and then stood up needs its diagonal as room height. A wardrobe 200 cm high and 60 cm deep needs just under 209 cm, which is a real problem in an old building with ceiling beams.

Guides instead of a product list

Without products, every page has to win on knowledge. The obvious move would be a page for every combination of type, axis and centimetre, thousands of them. Google calls that scaled content abuse, and a new domain with no reputation would run into trouble fast. So Nischler starts with 30 pages, one per common search pattern, and each one combines what's true for its cabinet type, its axis and its exact size.

The page for cabinets 30 cm deep, for example, says that A4 binders get tight: a binder is 28.5 cm deep, and the back panel and door take another 1.5 to 3 cm. The page for wardrobes 120 cm wide says such a wardrobe usually has two or three doors and needs as much free space in front as one door is wide. A test checks that each of the 30 pages has size notes, measuring tips, tips for the cabinet type and a set of questions and answers.

Every page also has the niche calculator, prefilled with the page's size. It subtracts what a niche loses: 0.5 cm of air per side for hinged doors, 3 cm for protruding handles, 2 cm for the skirting board. Give it the room height and it checks the tilt clearance too. It runs in the browser, and the site itself is completely static.

Each page also makes clear that there are no products yet. There's a beta bar at the top, and where the product list will go it says "Passende Produkte folgen" (matching products coming soon). Someone arriving from Google expecting cabinets to buy should see that straight away.

If the first wave works, the second one is already planned: pages with two axes, like "bathroom cabinet 30 cm wide 20 cm deep". Those are the queries from the autocomplete probe where shop filters fail.

Measuring without measuring on the site

In the beta the site counts nothing at all. No cookies, no counter, no third-party script. What I want to know is in Google Search Console: which queries a page shows up for, at what position, and how often it gets clicked.

I first built something else: a cookieless counter in Cloudflare D1 that stores path, time and referring domain per view and counts every click on "Zum Shop". It was briefly online with demo products, and within the first ten minutes the database held 86 page views and 81 shop clicks, almost none of them mine. New hostnames show up in public certificate logs right away, and these were most likely scanners posing as browsers and following every link. A click-through rate built on that would have been worthless. The counter now only counts requests carrying the Fetch Metadata headers real browsers send when navigating (Sec-Fetch-Mode: navigate), and clicks only when they come from one of Nischler's own pages (Sec-Fetch-Site: same-origin). It comes back with the products.

An image proxy is ready for stage 2 as well. If you embed product images straight from the shops' servers, every page view sends the visitor's IP to a dozen third parties. Nischler fetches the images itself and serves them from /bild/{id}, only the URL stored for that product and only raster formats, otherwise it would be an open proxy. Import, parser and LLM pass run on my machine against a local SQLite file, which is also where the API keys are. Only the searchable rows ever go online.

When I'll stop

The criteria are in the repository:

  • Stage 1 has been running since 11 October 2026. After 90 days, from 9 January 2027, I'll look at Search Console. If none of the 30 pages ranks in the top 30 for its search pattern, that's it.
  • If at least five pages rank in the top 30 and get clicks, stage 2 starts with real product data. Before that I'll check search volume in the Keyword Planner: under 50,000 searches a month across all size patterns, it isn't worth the effort.
  • Stage 2 then has a second hurdle. If fewer than 20 % of visitors click through to a shop after 90 days, the model doesn't hold up.

When the first 90 days are up, I'll write here what came out of it, even if the answer is "stop".

#seo#validation#llm#cloudflare

About the project

Nische 30 × 200 × 35 cm
Hochschrank Elmo B 36 · T 33 cm 6 cm zu breit
Beta

Nischler

Cabinets that fit your niche, to the centimetre.

A search engine for cabinets by exact width, height and depth across many shops. The beta has no products yet: guides for 30 common sizes and a niche calculator, run as an SEO experiment to see whether the pages find visitors first.

View project →

Keep reading