In one sentence: declare the competitor set in advance, detect every member with the same code path in the same pass, normalise names identically for everyone, and resolve ties against yourself — anything less and the number flatters you by construction.

Why asymmetry is the default failure

Nobody sets out to cheat. The bias arrives because the detector gets written and tested against your own brand name, and then extended to competitors as an afterthought. The classic shapes:

  • Different matching rules. Your brand matches on any substring; competitors match on exact name. "Acme" catches "Acme's pricing" but "Zenith Systems" misses "Zenith".
  • Different detection paths. Your brand is found by an LLM pass that understands context; competitors are found by a word list.
  • Asymmetric normalisation. "Acme" and "Acme Systems" fold into one entity for you, while the competitor stays split across two rows and each row shows half the real number.
  • Negative mentions counted as presence for you but not for them.

We shipped a version with several of these. A brand showed 31% share of voice and rank two; the honest figures were 0% and last. Nothing in the code looked wrong in isolation.

One pass, one code path, every brand in the set including yours. Ties resolve against you, not for you.

Who belongs in the set

Three tests, all of which have to pass:

TestWhy
A buyer could plausibly choose them insteadOtherwise you are measuring against a company nobody compares you to
They appear in answers to your actual question setA competitor who never shows up adds noise, not signal
Their name is unambiguous enough to detectA brand whose name is a common word will produce false positives for everyone

Adjacent-category companies are the common trap. They look like competitors in a positioning deck and behave like noise in the data, because engines do not surface them for the same questions.

Normalisation rules that hold for everyone

Write the rules once and apply them to every brand: strip legal suffixes, fold the common short form into the full name, handle the possessive, handle the domain form. Then test the rules against a competitor's name first — if the rule only ever got tested against your own, you do not know whether it works.

Changing the set is a methodology change

Share of voice is a share. Adding or removing a competitor changes the denominator, so every historical figure shifts. Version the set alongside the prompt set, record which version produced each run, and when you change it, either recompute history or start a new series — but say which you did.

The check that catches most of this

Take one answer where you were counted as present and one where a competitor was. Read both by hand. If the two judgements would not survive being swapped — if you would have counted the competitor's sentence differently — the detector is asymmetric, whatever the code says.