squirrelscan
GitHub

Sitemap Lastmod Drift

Checks that sitemap lastmod matches the page's own dateModified

Checks that sitemap lastmod matches the page’s own dateModified

Rule IDcrawl/sitemap-lastmod-drift
CategoryCrawlability
ScopeSite-wide
Severitywarning
Weight4/10

What it checks

For every crawled page that appears in a sitemap with a lastmod, the rule compares that lastmod against the page’s own strongest date signal: schema.org dateModified, else the dateModified-equivalent markup ([itemprop="dateModified"] meta / <time>), else the visible published date. Pages with no date signal at all are skipped: that is Content Freshness territory, not drift.

Which JSON-LD node the date comes from

Only the node that describes the document is read: an Article, BlogPosting, NewsArticle or similar, else a page-level node such as WebPage, FAQPage or Recipe. A sitewide WebSite, Organization, Product or SoftwareApplication node carries its own dateModified that has nothing to do with when this page changed, and Yoast and Rank Math emit one first in @graph, ahead of the article. Those nodes are ignored, and an article node is preferred over a page-level one wherever the two sit, so moving a sitewide node around the @graph cannot change the verdict.

Types may be written bare (Article), as a full IRI (https://schema.org/Article) or against the schema: prefix, and a node may claim several at once (["WebPage", "BlogPosting"] counts as the article). The date itself may be a plain string, a {"@value": "..."} wrapper, or a list of either, in which case the first entry that parses as a date is used.

If no document-describing node carries a usable dateModified, the rule falls through to the page’s own markup and visible date rather than borrowing the sitewide one. The same scoping is applied by Date Agreement.

The two directions are reported as separate checks, because they point at different code:

CheckFires whenUsual cause
sitemap-lastmod-behind-pagelastmod is older than the page’s dateModified by more than 7 daysStale cached sitemap, or a generator resolving publishedAt ?? updatedAt while the page renders updatedAt ?? publishedAt
sitemap-lastmod-ahead-of-pagelastmod is newer than the page’s dateModified by more than 30 dayslastmod stamped at build/deploy time instead of on content change

Each finding reports both dates and the gap in days. The gap is counted in whole elapsed days, so a difference has to reach the next whole day past the threshold before it warns: with the default behind_days = 7, a 7.5-day gap passes and an 8-day gap warns. Same-day and within-threshold differences never warn.

Lastmod being older than the page’s own dateModified is the more clearly wrong of the two: it tells crawlers not to bother re-fetching a page that has in fact changed.

Solution

A sitemap lastmod that disagrees with the page’s own dateModified points at the sitemap generator, not the content. Lastmod OLDER than the page’s dateModified tells crawlers not to bother with a page that has in fact changed - usually a stale cached sitemap, or a generator resolving publishedAt ?? updatedAt while the page renders updatedAt ?? publishedAt (a precedence inversion; both fields are present, so presence checks pass). Lastmod NEWER than the page’s dateModified usually means lastmod is stamped at build/deploy time. Drive both values from the same content-modification timestamp.

Options

This rule supports the following configuration options:

OptionTypeDefaultDescription
ahead_daysnumber30Days a sitemap lastmod may run ahead of the page’s own dateModified before warning
behind_daysnumber7Days a sitemap lastmod may lag the page’s own dateModified before warning

Configuration Example

[rules."crawl/sitemap-lastmod-drift"]
ahead_days = 30
behind_days = 7

Enable / disable

Disable this rule

[rules]
disable = ["crawl/sitemap-lastmod-drift"]

Disable all Crawlability rules

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

Enable only this rule

[rules]
enable = ["crawl/sitemap-lastmod-drift"]
disable = ["*"]

Type to search…

↑↓ navigate↵ openesc close