squirrelscan
GitHub

Date Agreement

Checks the visible date, schema dates and URL/title year agree

Checks the visible date, schema dates and URL/title year agree

Rule ID content/date-agreement
Category Content
Scope Per-page
Severity warning
Weight 4/10

What it checks

A page states its date up to five times: the visible byline, schema.org datePublished / dateModified, a year in the URL or the title, the sitemap lastmod, and the Last-Modified header. Content Freshness passes as soon as any of them exists and Content Dates reports how many pages carry them, so a page whose signals contradict each other passes both. The disagreement is the defect, and this rule is the only one that looks for it. (The sitemap side of the same question is Sitemap Lastmod Drift; this rule stays on the page.)

Four page-side signals are extracted and reported on every finding:

Signal Read from
Visible date The date the reader sees: a rendered <time>, byline/entry-meta markup, or a short date-only line at the top of main content
Schema document date datePublished / dateModified on a node that describes the DOCUMENT (Article, BlogPosting, NewsArticle, WebPage, FAQPage, …), @graph included
URL / title year A four-digit year in the URL path, else in the <title>
Last-Modified The HTTP response header
Check Fires when
byline-vs-schema-date The visible date and the schema document date are more than tolerance_days apart. Both values are named in the finding
visible-date-missing An Article-family node states dates the page never renders — a date only crawlers can see
url-title-year The year in the URL, else in the title, is not the year of either schema document date
schema-date-source Informational: the page shows a date, but its only schema date sits on a node that does not describe the page

Every visible date is measured against the closest schema date and the best pairing decides, so a page showing “Published 6 January · Updated 10 February” is telling the truth about both and stays quiet. A page-level node (WebPage, CollectionPage) alongside several visible dates is an index or an archive — those dates belong to the entries it lists, so nothing is compared.

visible-date-missing fires only when main content prints no date-shaped string anywhere. A date this rule declined to read as a byline is still a date on the reader’s screen, and “this page shows no date” has to be literally true to be worth saying.

Last-Modified is reported alongside the others but never raises a warning on its own: origins stamp it at deploy time far more often than at content-change time, so a disagreement there is not evidence of a defect.

What it deliberately does not report

Both of these are false positives that a naive version of this check produced in bulk, so they are guarded rather than tuned:

  • A date on a node that does not describe the page. A sitewide SoftwareApplication, Product or Organization node carries its own datePublished — the release date of that entity, not the publication date of the post it happens to sit beside. Taking the first datePublished in the document attributes one placeholder date to every page on the site. Only document-describing @types can raise a disagreement; a date from anywhere else is reported with its node type noted (schema-date-source) and never compared.
  • A date-shaped string that is not a byline. A byline is a position, not a pattern: running prose (“INP replaced FID on March 12, 2024”) and outbound citations (<a href="https://web.dev/...">March 12, 2024</a>) are date-shaped and are not this page’s publication date. A candidate must sit near the top of main content and look like byline markup — a <time> element, byline/entry-meta-style markup, or a short line that says nothing beyond the date. An anchor’s own text never counts.

A WebPage node carrying dates is not required to render them: WordPress SEO plugins emit one on every page of a site, contact form included, so demanding a visible date there would warn on everything.

Solution

A page states its date more than once - the visible byline, schema.org datePublished/dateModified, a year in the URL or title, the sitemap lastmod, the Last-Modified header - and readers and crawlers do not all read the same one. When they disagree, at least one is wrong, and presence checks cannot tell you which: they pass as soon as any single signal exists. Drive every date on the page from ONE content timestamp. If the visible byline disagrees with the schema, fix whichever renders from the wrong field (a common cause is the template printing a build-time or hardcoded value while the schema prints the CMS field). If the schema carries dates the reader never sees, render the date in the article header - Google asks for a visible date on dated content, and a date only crawlers can see is not one. Check the schema date is attached to the node describing the page (Article/BlogPosting/WebPage): a datePublished on a sitewide SoftwareApplication or Organization node is that entity’s own date and says nothing about this page.

Options

Option Type Default Description
tolerance_days number 1 Days the visible byline date may differ from the schema document date before warning

Configuration Example

[rule_options."content/date-agreement"]
tolerance_days = 1

Enable / Disable

Disable this rule

[rules]
disable = ["content/date-agreement"]

Disable all Content rules

[rules]
disable = ["content/*"]

Enable only this rule

[rules]
enable = ["content/date-agreement"]
disable = ["*"]

Type to search…

↑↓ navigate openesc close