System · InfoFrame
AI Visibility Tracker
In production
People are starting to ask instead of search. That moves the question from where you rank to whether you get mentioned at all. This measures it, weekly, against named competitors.
Facts
- Status
- In production, five brands
- Origin
- Fork of open source (Elmo, MIT). 177 of 964 commits are mine.
- Stack
- TypeScript · TanStack Start · Postgres · Drizzle · pg-boss
- Engines
- ChatGPT, Perplexity, Gemini, Copilot, Claude, Google AI Overview
- Volume
- Around 96 prompts, roughly 3,600 measurements a month
- Hosting
- Coolify on our own Hetzner box
- Proof
- ai.infoframe.no
What is mine, and what is not
This was not built from scratch. It is a fork of Elmo, an open source project under the MIT licence. Of 964 commits in the history, 177 are mine. The core, the provider abstraction and much of the scoring come from upstream.
My layer is the features around it: the citation gap analysis, the technical readability scans, trials, client reports, organisation scoping so several customers can share one database, and all the operations and incident handling underneath.
I could leave this paragraph out. But not reinventing the wheel is my entire working method, so my largest system ought to be the clearest example of it, not the thing I am vaguest about.
How the questions actually get asked
Nine adapters sit behind one interface. Four scrape the assistants' real consumer interfaces, four talk directly to APIs, and one is a stub for testing. Which ones are live is set with a single environment variable, not in code.
Every prompt runs five times per model, in parallel, because the answers vary between runs. One answer is an anecdote. Five is a frequency.
The job reschedules itself afterwards, with a key that stops one brand getting two queue entries at once. A maintenance job every five minutes chases whatever is overdue, and raises an alert if something has been waiting more than half an hour.
The arithmetic is boring on purpose
Share of voice is the brand's mentions divided by the brand's plus the competitors', and returns no value rather than zero percent when nobody was mentioned. That distinction matters: no data is not the same as no visibility.
Ranking between brands is plain text ordering, not a language model. Citation gaps are computed deterministically over thirty days. The model is only allowed to write the explanation afterwards, never the number.
Sentiment is the one place a model actually decides something, and it only runs when the brand was mentioned at all. That keeps the cost at a few kroner a month instead of thousands.
The expensive part is not the code, it is the runs
Every measurement costs money at a third party. So one of the jobs has zero retries, deliberately: an automatic retry would re-bill an entire brand's burst.
In July one target never finished. The queue therefore treated its prompts as permanently overdue and ran them again and again: around 21,000 runs in a week where the norm is about 15. The fix was an hour-long throttle between chases.
The uptime and deploy watchdogs exist for the same reason. One came after four and a half hours of silent overnight downtime, the other after four hung deploys filled the disk to 91 percent.
What this is not
It is not a product you can buy. The cloud tier does not exist, and starting the platform in that mode stops it at boot. Trials are a simple sidecar with no plan codes and no payment.
The data collection has not proved stable yet. One of the collectors was at fifty percent successful runs when it was last measured, and that is not closed.
Five brands is not many. The numbers above are real, but they are not proof that this scales to fifty customers.