---
name: "page_family_seo_audit"
description: "Audit every page one template produces as a family, not as single pages: sample the family, read the deployed HTML, check indexability and structured data, test whether search and answer engines can tell the pages apart and credit a passage to the right page, and hunt template seams that repeat, thin out, or contradict across the set, with fixes ranked worst first. Triggers on 'audit these location pages', 'template pages', 'pages look too similar', 'Google picks the wrong page', 'family audit', 'programmatic pages not indexing', or any set of pages built from one template and one data source."
---

# Page Family SEO Audit

## Purpose

Audit a page family: all the pages one template and one data source produce, such as location pages, product pages, integration pages, or comparison pages. A single page can look fine while the family fails, because the faults live between pages: titles that collide, facts that contradict, passages repeated so often that no page owns them, and records too thin to stand apart. This skill is the after launch audit. Use programmatic SEO skills to design a family before it ships and a general SEO audit for a mixed site. Use this one when a family is live and the question is how its pages behave as a set.

## Workflow

1. **Define the family before touching a page.** Name the template, the data source, the URL pattern, and the total count. Pages that share a layout but come from a different data source are a different family. Write the count down: every later claim is about a sample of that count, never about the family as if all of it was read.
2. **Sample with intent, not convenience.** Follow `references/sampling.md`. The sample always includes the extremes and the edge records, plus a random slice. Audit the sample by hand and run the tool over the largest set you can fetch.
3. **Run the family tool first.** `bin/family_audit.py` reads local HTML files or URLs and reports word counts, titles, meta descriptions, canonicals, robots meta, H1s, JSON-LD types and parse errors, schema values that do not appear in visible text, paragraphs repeated across half or more of the family, and pairwise similarity from 5-word shingles. Run it before hand reading so the hand reading can chase its flags. Command: `python3 bin/family_audit.py --urls urls.txt --json report.json` with one URL per line, or pass files directly.
4. **Check indexability at family level.** For each sampled page confirm it returns 200, is not blocked by robots.txt, carries no stray noindex, self references its canonical, appears in the sitemap, and is linked from inside the site. Then check coherence across the set: sitemap, internal links, redirects, and canonical tags must all point at the same preferred URL for each record. Google treats a canonical tag as a hint and weighs those other signals too, so a family whose signals disagree will have its canonicals chosen for it.
5. **Score differentiation.** Use `references/scoring.md`. For each sampled page, strip the shared template text in your head and ask what is left that is true only of this record. Compare title, H1, opening paragraph, and the facts a reader came for. Pairs the tool flags at high similarity get read side by side.
6. **Run the passage attribution test.** Pick one distinctive, true passage from each of three sampled pages, a fact no sibling should share. Search the exact passage in quotes and note which URL surfaces. Then check that no sibling carries the same passage. If a sibling carries it, or the wrong page surfaces for it, the family has an attribution fault: engines have no clean way to credit the passage to its owner. Record the query, the passage, and the result URL as evidence.
7. **Check structured data against visible text.** Parse every JSON-LD block in the sample. Each block must parse, use a type that fits the page, and describe content a reader can see on that page. Structured data must be a true representation of the page content, and marking up content that is not visible breaks Google guidelines. Cross page check: values such as price, name, address, rating, and availability must not leak from one record into a sibling, which is the classic template variable fault.
8. **Hunt the seams.** Work `references/seam-checklist.md` line by line. Seams are where the template meets the data: empty fields rendered as blank lines or placeholder words, units and dates in mixed formats, one record with a fact its siblings contradict, shared paragraphs doing work they should not do, and sections that vanish on thin records and leave the page unbalanced.
9. **Rank fixes worst first and write the report.** Follow the Output Contract. One fix at template level usually repairs hundreds of pages, so rank by pages affected times harm, not by how interesting the fault is. Separate template fixes (change once, heal the family) from data fixes (repair the record) and retirement calls (merge or remove records that cannot stand apart).

## Output Contract

- Header states the family: template, data source, URL pattern, total page count, sample size, and how the sample was chosen.
- A family score from `references/scoring.md`, with the six dimension scores shown and an evidence line for each.
- Findings ranked worst first. Each finding names the fault, the sampled pages that prove it, how many pages in the full family likely carry it and how that estimate was made, why it matters in one sentence, and the fix labeled template, data, or retire.
- A differentiation table for the sampled pages: title, H1, word count, similarity to nearest sibling, and the one fact that belongs only to that page. A row with no unique fact is a finding, not a blank.
- Attribution test results: the exact quoted query, the passage, the URL that surfaced, and pass or fail for each tested page.
- A short list of pages recommended for merge or removal, each with the reason and what happens to its URL.
- Anything not checked is listed as not checked. A sample based claim never gets written as a whole family claim.

## Operating Rules

- Read deployed HTML, not templates or CMS previews. The fault that matters is the one a crawler and a reader actually get, including what the server renders before any script runs.
- Similarity is evidence, not a verdict. The tool measures shared wording with 5-word shingles and Jaccard similarity, where identical text scores 1.0 and text with no shared shingles scores 0. No search engine publishes a similarity threshold, so never report a score as a search engine cutoff. High similarity starts a hand read, it does not finish one.
- Shared boilerplate is not automatically a fault. Navigation, legal text, and a short shared service description are normal. A seam becomes a finding when the shared text is the primary content of the page, or when it leaves too little that is unique to the record.
- Google clusters pages whose primary content is the same or very similar and shows one of them. Frame duplication findings as clustering and lost pages, not as a penalty, unless there is a manual action notice in Search Console.
- Scaled content abuse is a purpose test: many pages made mainly to manipulate rankings and not to help users, no matter how they were made. Cite it only when the sampled pages genuinely add nothing for a reader, and name the missing value.
- Do not invent indexation numbers. Report Search Console figures only when an export or a live check in this run produced them, and label lab checks, tool output, and field data separately.
- Respect crawl limits on live sites. Fetch at a polite rate, stop on 429 or blocking responses, and fall back to an exported URL list plus local HTML where fetching is refused.
- Style stays plain. No em dashes. No filler. Every finding must change a decision, or it gets cut.
