Updating an existing article is harder than writing a new one in one specific way:
You already have content, but you do not always know what to add.
A keyword tool can show related terms. A content brief can list possible sections. But a live SERP can show what searchers are currently being offered:
- comparison sections
- setup steps
- examples
- pricing context
- implementation notes
- common pitfalls
- glossary explanations
- evaluation criteria
- tool alternatives
This post shows a small pattern for building a content gap finder from SERP result patterns. A SERP API such as TalorData SERP API can collect structured search results; your code can compare those signals with an existing page outline.
What the tool should do
Input:
- target keyword
- current page title
- current page headings
- optional current page summary
- top SERP result titles, snippets, and URLs
Output:
- recurring SERP topics
- page formats that appear often
- candidate missing angles
- gaps that need human review
- things not worth adding
The last point matters. A gap finder should not turn every SERP detail into an editing task.
A simple input format
Start with your existing page outline:
{
"page_url": "https://example.com/blog/serp-api-guide",
"target_keyword": "serp api guide",
"title": "SERP API Guide for Developers",
"headings": [
"What is a SERP API?",
"How search result APIs work",
"Common use cases",
"Basic API workflow"
]
}
Then normalize the SERP results:
{
"query": "serp api guide",
"location": "United States",
"captured_at": "2026-07-22T09:00:00Z",
"results": [
{
"position": 1,
"title": "How to Use a SERP API for SEO Monitoring",
"url": "https://example.com/blog/serp-api-seo-monitoring",
"snippet": "Learn how to collect ranking data and monitor search results over time."
}
]
}
The example is generic. Replace field paths with the actual response schema from your provider.
Normalize text
import re
from collections import Counter
from urllib.parse import urlparse
def normalize_text(value: str) -> str:
value = value.lower()
value = re.sub(r"[^a-z0-9]+", " ", value)
return re.sub(r"\s+", " ", value).strip()
def tokens(value: str) -> set[str]:
stopwords = {
"a", "an", "the", "and", "or", "to", "of", "for", "in", "with",
"how", "what", "why", "is", "are", "your", "from", "by"
}
return {token for token in normalize_text(value).split() if token not in stopwords}
This is intentionally simple. For a first version, readable rules are easier to review than a model-driven score nobody trusts.
Extract current page topics
def page_topic_tokens(page: dict) -> set[str]:
text = " ".join([page.get("title", ""), *page.get("headings", [])])
return tokens(text)
The outline is not the full article, but it is often enough to find obvious missing areas.
Extract SERP topics
def result_topic_tokens(result: dict) -> set[str]:
text = " ".join([
result.get("title", ""),
result.get("snippet", ""),
urlparse(result.get("url", "")).path.replace("-", " ")
])
return tokens(text)
def serp_topic_counts(serp: dict) -> Counter:
counts = Counter()
for result in serp["results"][:10]:
weight = max(1, 11 - result.get("position", 10))
for token in result_topic_tokens(result):
counts[token] += weight
return counts
This gives higher weight to topics appearing in higher positions.
Find candidate gaps
def find_candidate_gaps(page: dict, serp: dict, min_score: int = 5) -> list[dict]:
page_tokens = page_topic_tokens(page)
serp_counts = serp_topic_counts(serp)
gaps = []
for topic, score in serp_counts.most_common():
if score < min_score:
continue
if topic in page_tokens:
continue
gaps.append({
"topic": topic,
"score": score,
"reason": "Appears in SERP result titles, snippets, or URL paths but not in the current page outline"
})
return gaps[:20]
The output is a candidate list, not an editing plan.
Add page format detection
Content gaps are not only words. They can also be formats.
def detect_page_format(result: dict) -> str:
text = normalize_text(" ".join([result.get("title", ""), result.get("url", "")]))
if "pricing" in text:
return "pricing_context"
if "alternative" in text or "compare" in text or "comparison" in text:
return "comparison"
if "guide" in text or "tutorial" in text or "how to" in text:
return "guide"
if "docs" in text or "documentation" in text:
return "documentation"
if "review" in text:
return "review"
return "unknown"
def format_counts(serp: dict) -> Counter:
return Counter(detect_page_format(result) for result in serp["results"][:10])
A page can be missing a topic, but it can also be missing a useful format. For example, an article may explain a concept but never include comparison criteria, implementation steps, or review questions.
Build a review output
def content_gap_report(page: dict, serp: dict) -> dict:
return {
"page_url": page.get("page_url"),
"target_keyword": page.get("target_keyword"),
"candidate_topic_gaps": find_candidate_gaps(page, serp),
"serp_page_formats": dict(format_counts(serp)),
"review_note": "Treat these as candidates. Review against search intent, page purpose, and editorial focus before adding sections."
}
This kind of output is easy to pass to an editor or SEO reviewer.
Add a reject list
Not every gap should be filled.
Add reasons to reject a candidate:
- off-topic for the page purpose
- belongs on a separate page
- appears only because of one outlier result
- too commercial for an educational page
- too beginner-level for an advanced guide
- outside product or editorial scope
- not useful for the target reader
A useful gap finder should help reduce random additions, not encourage them.
Where the SERP API fits
The SERP API is the collection layer. Your comparison logic is the analysis layer.
One useful workflow:
- Collect SERP results for the target keyword
- Normalize titles, snippets, URLs, and positions
- Extract recurring topics and page formats
- Compare them with the current page outline
- Generate candidate gaps
- Review what to add, ignore, or move to another page
If you need structured search result data for this workflow, TalorData can support the SERP collection step while your team owns the gap rules and editorial decisions.
What I would not automate
I would not automatically rewrite the page from the gap report.
SERP patterns can reveal missing angles, but they do not know your page purpose, brand voice, product limits, or editorial priorities.
Use the finder to create a review list. Let a human decide whether each gap belongs in the update.
Final thought
A content gap is not just "something competitors mention."
A useful content gap is a missing angle that matches the search intent, helps the target reader, and fits the page you are updating.
The SERP can help you find candidates. The editing decision still needs judgment.
Top comments (0)