SEO report template

Four real files, not a page describing one. A seven section monthly report, a findings tracker with a decision and an owner on every row, and a KPI sheet that states where each number came from.

An SEO report should be seven sections and three pages, not thirty. What changed, the numbers behind it, what was fixed, what was published, what is open and who has it, what you are deliberately not doing, and what happens next. The sixth is the one no template has and every client relationship needs.

The report, section by section

Seven headings, each with the prompts that sit under it and the thing that does not belong in it. The Word and Markdown files are exactly this, with the guidance as italic lines you delete as you fill it in.

1. What changed this month

Three to five sentences a busy reader can stop after. If they read nothing else, this is what they know.

  • The one thing that moved, up or down, and by how much.
  • The one thing we shipped that we expect to move next.
  • Anything that needs a decision from you this month.

Leave out. A recap of what SEO is, a list of everything that was touched, and any sentence that would be true in any month of any engagement.

2. The numbers

The small set of figures worth tracking, each with the date and the tool it came from. Use the KPI tab of the spreadsheet.

  • Clicks and impressions, this period against the same period last year rather than against last month.
  • The queries where impressions held and clicks fell, which is where a result is being answered without a visit.
  • Conversions or enquiries attributed to organic, with the attribution model named.
  • Anything that moved more than you can explain, flagged as unexplained rather than narrated.

Leave out. Rankings for keywords nobody searches, a domain authority score, and any metric that has never once changed a decision in this engagement.

3. What we fixed

Shipped work only. One line each, linked to the finding it closes in the tracker.

  • The finding, the fix, and the date it went live.
  • Where it applies: one page, one template, or site wide.
  • What we expect it to change, and roughly when we will be able to tell.

Leave out. Work in progress, work planned, and anything where the fix is written but not deployed. Those belong in section 5.

4. What we published

New and updated pages, with the reason each one exists. A page with no reason is the thing to catch here.

  • The URL, and the question it answers for a reader.
  • Whether it is new, an update, or a merge of pages that were competing.
  • For updates: what specifically changed, since a date bump on unchanged content is a pattern worth nobody's time.

Leave out. Word counts, publishing cadence as an achievement, and a list of pages with no statement of what any of them is for.

5. What is open, and who has it

Everything found and not yet fixed, with a name against it. This is the section that makes the report a working document rather than a summary.

  • Findings waiting on us, with the date we expect to ship them.
  • Findings waiting on you, stated plainly, with what specifically is needed.
  • Anything blocked, and by what.

Leave out. The full findings list. Link the tracker instead; a report that reprints 200 rows is the report nobody opens.

6. What we are not doing, and why

The section no template has. Everything deliberately deprioritised, with the reason, so nobody has to reconstruct the decision in six months.

  • Findings we judged not worth fixing, and what made them not worth it.
  • Work the data does not support yet, and what would change that.
  • Anything we were asked for and advised against, with the advice restated.

Leave out. Silence. A thing left undone with no reason recorded reads as a thing forgotten, and it will be raised as one.

7. Next month

Three to five items, in order, with the largest first. Anything longer than that is a list rather than a plan.

  • The next thing to ship, and why it is next rather than something else.
  • What we need from you and by when.
  • What we will be able to say in the next report that we cannot say in this one.

Leave out. A rolling backlog copied forward each month. If an item has appeared three times without moving, it belongs in section 6.

The numbers, and what each one does not prove

The third column is the one other templates leave out, and it is the one that stops a figure being over-read in a meeting. A simulated lab score reported as what visitors experienced is the most common version of that.

MetricWhere it comes fromWhat it does not prove
Clicks from organic searchSearch Console, Performance report, Web search typeReported on a delay of a couple of days and deduplicated by property. It is not sessions and will not match analytics.
ImpressionsSearch Console, same reportAn impression is not a reader. Rising impressions with flat clicks usually means being found for things you do not deserve to win.
Queries with impressions and no clicksSearch Console export, filteredThe most useful row here. It does not tell you why, only where to look.
Average positionSearch ConsoleAn average across every impression, so it moves when your query mix changes and nothing about your rankings did.
Indexed pagesSearch Console, Pages reportA count, not a health measure. A site can index everything it has and deserve none of it.
Enquiries or conversions from organicYour analytics, with the attribution model named in the cellAttribution is a model and every model is wrong somewhere. Name which one, and compare like with like over time.
Core Web Vitals, field dataChrome UX Report, 75th percentile, 28 day windowOnly exists once a URL has enough real traffic. If there is no field row, do not substitute the lab number.
Core Web Vitals, lab scoreLighthouse or PageSpeed InsightsA simulation on a shared machine. It moves between runs on an unchanged page, so never report a single reading.
Referring domainsWhichever backlink index you use, named in the cellEvery index sees a different web. The trend within one tool is meaningful; the absolute number is not comparable to anybody else's.
Assistant mention rateYour own prompt set, run against each assistant, fresh conversation per questionA rate over a prompt set, not a ranking. Re-run it: these systems are not deterministic and one run is an anecdote.

The findings tracker

Twelve columns, and every fixed-value one is a dropdown in the workbook. There is deliberately no “noted” status: a row with nobody’s name on it is a row nobody will action, and recording it anyway is how a report gets delivered and never opened.

ID
A stable reference you can quote in a report or an email. F-001 onwards.
Finding
What is wrong, in one sentence, in language the person fixing it would use.
Area
Which gate it belongs to.ReachReadUnderstandQuoteSpeedSecurity
Severity
How much it costs while it is unfixed.CriticalHighMediumLow
Scope
How many pages it affects.One pageOne templateOne sectionSite wide
Evidence
The URL, the header, the line of markup. A finding with no evidence is an opinion.
Decision
What we are going to do about it. There is deliberately no "noted".Fix nowFix nextAcceptNeeds a decision
Owner
A person, not a team. A row with no name is a row that will not move.
Status
Where it is.OpenIn progressShippedVerifiedNot fixing
Target date
When it is expected to ship. Blank is allowed for Accept, and for nothing else.
Verified on
The date somebody re-checked the live page and confirmed it. Shipped is not verified.
Notes
Anything the next person needs, including why an Accept was accepted.

Seeded with ten checks, in failure-rate order

The files open with these already in them, sorted by how often the thing is actually broken rather than by category. Importance is an opinion and a rate is not.

IDFindingAreaSeverityBroken on
F-001The canonical tag points at a URL that redirectsRequest the canonical URL directly. It has to return 200 with no hop.ReachHigh35%
F-002No machine readable publish or modified dateView source and search for the year. A date rendered by JavaScript is not a date.UnderstandMedium32%
F-003No author named in the markup or in structured dataLook for a byline in the HTML and an author property in the JSON-LD. Both, not either.UnderstandMedium25%
F-004HTML document heavier than the content justifiesDocument size before images and scripts. Usually inlined state or duplicated component markup.SpeedMedium25%
F-005Structured data absent, or present and failing to parseExtract every application/ld+json block and parse it. One trailing comma discards the whole block silently.UnderstandMedium13%
F-006A noindex directive on a page that should be indexedCheck the meta robots tag and the X-Robots-Tag header. They are set in different places by different people.ReachCriticalnot rated
F-007The server answers 403 or 429 to a declared crawlerFetch with curl and no user agent, then with a browser string, and compare the status codes.ReachCriticalnot rated
F-008Content only present after JavaScript runsFetch the raw HTML and count visible words. A browser will always make this look fine.ReadCriticalnot rated
F-009An AI crawler is disallowed in robots.txtEvaluate robots.txt once per named agent. A bot with its own group ignores the wildcard rules entirely.ReachHighnot rated
F-010Sections cannot be lifted as a standalone answerTake one paragraph out of context and read it. If it needs the three above it, it cannot be quoted.QuoteLownot rated

Failure rates are from our own audit of 88 professional marketing sites that returned HTML to our fetcher, published at visibility100x.com/research/geo-agency-audit/. Rows with no rate are checks that did not fail often enough in that sample to have earned one; they are ordered by severity instead.

Two formats we are not publishing, and why

No PDF

A PDF cannot be typed into, so a PDF template is a picture of a template. Fill in the Word or Markdown version and export a PDF from that when you send it. That way next month you edit a document rather than rebuilding one.

No Looker Studio template

A Looker Studio template lives inside somebody’s Google account and is shared out of it, which is a hosting commitment rather than a file. We would rather publish nothing than publish a link that quietly stops working when an account changes hands.

Filling in the findings tab without doing it by hand

Three of the four columns you would otherwise type out are things a tool can answer.

  1. Get the findings.The free audit runs every check against your live site and returns them sorted by severity, with the evidence attached to each one. That is the Finding, Area, Severity and Evidence columns filled in for you.
  2. Fill the Decision and Owner columns yourself.No tool can do this half, and it is the half that decides whether the tracker is a working document or a spreadsheet. One question per row: if this were fixed tomorrow, what would be different?
  3. Use the content actions tab for pages rather than faults.Keep, update, merge or delete, one row per URL.How to run a content audit is the method behind that tab, including the three questions that settle almost every page.

Questions people ask

What should an SEO report include?

What changed and what it means, the small set of numbers that support it, what was shipped, what is still open and who has it, what you are deliberately not doing, and what happens next. Seven sections. Anything longer is an inventory, and an inventory hands the hard part back to the reader with more work attached.

Is this template free?

Yes, and there is no form in front of it. Download the files, edit them, put your own logo on them and send them to a client as your own. No attribution required and no account needed. Gating an artefact behind an email is the obvious growth lever and it is the wrong one.

Can I use it in Google Sheets?

Yes. Open the workbook in Google Sheets with File then Import, or use the CSV if you only want the findings tracker. The dropdowns are the one thing that do not survive the import cleanly; the values are listed on this page so you can recreate them in a minute with Data validation.

How often should I send an SEO report?

Monthly for most engagements, and the honest caveat belongs in the first one: crawling, indexing and search reporting all lag, so the first genuinely readable read on new work is three to six months in. A monthly cadence is for accountability and for decisions, not because the numbers move monthly.

Why does the tracker have no "noted" status?

Because a finding with no decision and no owner is not a finding, it is a sentence. The single most common way an audit fails is that everything gets recorded, nothing gets assigned, and the document is admired once and never opened again. Every row here ends in fix now, fix next, accept, or needs a decision.

Why are the findings ordered that way?

By how often the thing is actually broken on real sites, taken from our own audit of 88 professional marketing sites, rather than by category. Importance is an opinion and a failure rate is not. A check can matter enormously and almost never fail, which makes it a poor use of an afternoon.

Is there a PDF version?

No, on purpose. A PDF cannot be typed into, so a PDF template is a picture of a template. Fill in the Word or Markdown version and export a PDF from that when you send it, which gives you a document you can update next month rather than one you have to rebuild.

What about a Looker Studio template?

Also no, and for a different reason. A Looker Studio template lives inside somebody's Google account and is shared out of it, which is a hosting commitment rather than a file. We would rather publish nothing than publish a link that quietly rots when an account changes hands.

Fill the findings tab
from your own site

Free account, no card. Paste your URL and get a real, scored report of your AI and search visibility.

Measuring rankings in