Search Console Regex Not Working? How to Test and Fix It
About 26 minutes
By now we can write pretty good regex: we can isolate brand and non-brand, pull out long queries, pick out questions, comparisons and price queries, handle messy spellings, and analyze whole sections of the site. But there's a problem more dangerous than a regex throwing an error: a regex that runs perfectly normally, returns results, and you think it's right, when in fact it's returning a different segment from the one you wanted. That's far more dangerous than an obvious error.
The first rule: a regex that runs isn't necessarily a regex that's right
You want the comparison queries, and you wrote:
(compare|versus|difference between| or )- compare iphone and samsung
- iphone versus samsung
- difference between macbook air and pro
- iphone or samsung
- is shipping free or not
- is the warranty one year or two
The first four queries are great. But the last two? They contain " or ", so the regex carried out the rule correctly, but the segment itself isn't what you meant. The problem isn't that the regex is "broken"; it's that the rule we wrote is wider than the question we're trying to answer.
- 1
False positive — a result showed up, but it shouldn't be in the group (like "is shipping free or not") - 2
False negative — a result should be in the group, but didn't show up (like "iphone vs samsung", since the pattern has no vs)
Don't start with the big regex
Say you want a brand regex that covers smart store, smartstore, smart-store and smrt store. It's better to start with smart store, test, then smart ?store, test, then smart[- ]?store, test, then add the typo, test. Each time you know exactly which part you added, and which new results showed up because of it.
- 1The simplest pattern possible
- 2Test
- 3Add one part
- 4Test
- 5Add one part
- 6Test
Same as we did in Python: a small piece of code, print the result, understand it, then add more.
You need test cases before you run it
Before you put a regex into Search Console, write yourself some examples: what must show up, and what must not. Now, when you run the pattern, you have an expectation; you're not looking at the results and saying "looks good". These are like very simple unit tests for regex.
A very important debugging question
Every time extra results show up, ask: how did the regex match this part? For example, product showed up in best-product-photography because the text is inside the URL. Search Console does a partial match by default, so the regex can match any part of the text unless you use ^ or $. When you ask "which part matched?", you reach the problem faster.
Another common problem: an anchor in the wrong place. Say you want queries that start with "how", but you wrote how$ by mistake:
how$- how to choose a laptop
- laptop how
You're saying "queries that end with how", not "start with how". The regex can run and return very few results, and you think people don't search with "how", while the problem is the pattern. Read the regex out logically every time: ^how means "the start of the text, then how". how$ means "how, then the end of the text".
The most important question when you take a ready-made regex
You might take a pattern from an article, Stack Overflow, ChatGPT or a colleague. Don't only ask "does it work?". Ask "which regex engine was it made for?", because not every regex on the internet is the same regex Search Console understands. Search Console uses RE2. You don't need the programming details; what matters is that there are several regex engines, and some features that work in PCRE or Perl aren't supported in RE2.
An important example: lookahead, lookbehind and backreferences
You might see something like this online, and it doesn't matter now if you understand the whole pattern. What matters is knowing that the part (?=...) is called a positive lookahead, and RE2 doesn't support it:
iphone(?=.*price)The negative lookahead (?!...) isn't supported either:
^(?!.*repair).*iphone.*And if you find a lookbehind, (?<=...) or (?<!...), those aren't supported in RE2 either. Same goes for backreferences like \1.
For every symbol, and whether it works in Search Console or only in Python, keep the regex cheat sheet open.
An important point about using AI
If you tell an AI model "make me a regex for queries with iphone but not repair", the model might give you a pattern with a negative lookahead. The fix isn't to say "regex is useless"; it's to know the limits of the environment you're working in. It's better to be clear from the start:
So how do I include A but exclude B without a lookahead? Don't try to squeeze all the logic into one clever pattern. In Search Console you can use the filters that are there: isolate iphone with one filter, and exclude repair with a separate filter, or do the analysis in stages.
A problem: an invalid regex and no results
Google explains that an invalid regex can return no matches. So if a pattern returns zero, don't immediately assume "there's no data". The pattern could be wrong, or use unsupported syntax, or be missing an escape, or have a group that isn't closed, or you could be searching for a phrasing that really isn't there. You need to tell them apart.
- 1iphone — are there results?
- 2
(iphone|samsung) — still there? - 3
(iphone|samsung).*\d — still there? - 4
^(iphone|samsung).*\d{4}$ — now, where did the results stop? - 5
The problem started after adding which part? That's simple binary debugging
Same idea with a long pattern like (?-i)^https://example\.com/(blog|guides)/.*(2025|2026).*\.pdf$. Take it apart piece by piece: (?-i) case-sensitive, ^https://example\.com/ start with the domain, (blog|guides) the blog or the guides, .* anything after it, (2025|2026) the year has to appear, .* anything, \.pdf$ and it ends in PDF. If you don't need PDFs at all, remove that part; if you don't need case sensitivity, remove it. Every part of a pattern needs a reason.
.* everywhere because you saw it in examples. Search Console does a partial match by default, so if you want "price", you don't need .*price.* in most cases. Use .* when it has a real job inside a bigger pattern.Understanding .* properly: the order of the words
iphone.*price means "iphone, and then, anywhere after it, price", in exactly that order.
How many of the two queries will match iphone.*price? (Think about the order.)
iphone.*price- iphone 17 price
- price iphone 17
.* doesn't mean "the two words in any order"; it allows characters between two parts in the order you wrote them. If you need both directions: (iphone.*price|price.*iphone). But ask yourself: do I need that at all? Maybe the simple price segment (price|pricing|cost|how much) plus reviewing the queries for one particular page is simpler.
Another mistake: a character class isn't a group
We covered it in the messy-queries lesson, but it's one of the most common debugging mistakes. You want "price or cost", and you wrote [price|cost] by mistake:
[price|cost]- iphone price
- iphone cost
- buy iphone
- laptop
[price|cost] means "one character from: p r i c e | c o s t", and "laptop" has a p, a t and an o in it. [] picks one character, not a word. The right way is (price|cost).(price|cost)- iphone price
- iphone cost
- buy iphone
- laptop
Another mistake: what exactly does the ? apply to? In smart ?store, the ? applies to the space before it. But if you wrote smart store?, the ? applies to the last e: a completely different pattern. So when you see a quantifier like ?, +, * or {n}, ask: what exactly does it apply to?
A bug versus a limitation
product instead of ^https://example.com/product/ when your goal is a specific structure. A limitation: the pattern works as you designed it, but the method itself has limits, like ^\S+(\s+\S+){6,}$, which relies on spaces, so it won't split iphone-17-pro-max into separate words. That isn't a bug; it's a known design. If you understand the difference, you'll know when to fix the regex and when to change the way you analyze.You have (price|cost|how much) against: iphone price, iphone cost, how much is an iphone, iphone pricing, iphone prices. What's the false negative? Fix the pattern.
- iphone price
- iphone cost
- how much is an iphone
- iphone pricing
- iphone prices
iphone pricing is the false negative: pricing doesn't contain price. iphone prices is fine, because prices does.
The practical test
You have: compare iphone and samsung, iphone versus samsung, difference between macbook air and pro, iphone vs samsung, is shipping free or not, is the warranty one year or two, best iphone, iphone price.
A comparison segment without false positives
Build a comparison regex that covers the main comparison cases, without bringing back "is shipping free or not" or "is the warranty one year or two" as extra results.
- · compare iphone and samsung
- · iphone versus samsung
- · difference between macbook air and pro
- · iphone vs samsung
- · is shipping free or not
- · is the warranty one year or two
- · best iphone
- · iphone price
A thinking test
After this lesson, I don't care whether you memorized "lookahead isn't supported, lookbehind isn't supported". That's important information, but it isn't the goal. The goal is that as soon as you get a new regex, you ask: do I understand every part of it? Is it RE2-compatible? What do I expect to show up? What do I expect not to show up? What are the false positives? What are the false negatives? Is the pattern wrong, or is the method itself limited? If you do that, you're no longer someone who copies regex. You can build it, test it and fix it.
Before the next lesson
We've covered almost all the tools we need in this course. The next step doesn't need many new symbols, and it's the most important one: how to bring it all together and turn regex from a filter into a full SEO analysis. We start with a question, build a segment, check it's right, read the clicks, impressions, CTR, position and the change over time, and then ask: what decision or investigation should come out of the data? That will be the last lesson before the final project.
Well done, you reached the end of the lesson.