Every page on the web is claiming something about its own age. The byline says when it was published, the markup says when it changed, the server says when it was last written, and the footer says what year it is. In an AI answer, those claims are inputs to a judgement about whether the page is current — and they are also the easiest thing on a site to fake accidentally, by bumping a date on every deploy until it means nothing.
This article is about the three dates that matter, what each one is allowed to say, how the scanner reads them, and how to keep them honest without turning every typo fix into a freshness claim.
The three dates, and what each one means
| Signal | What it is allowed to say | What it should never say |
|---|---|---|
datePublished | The first time this page was published. | A new date because the page was edited; it is not an edit date. |
dateModified | The last time the substance of the page changed. | A build timestamp, a deploy time, or a date moved by a template. |
article:modified_time | The same claim as dateModified, in an older meta-tag form. | A second, different date that contradicts the JSON-LD. |
Last-Modified header | When the response was generated or the resource last changed, depending on the stack. | A guarantee about content; it is a server fact, not an editorial one. |
The distinction that matters is between publication and revision. A page has one first publication; it can have many revisions. Collapsing the two into a single "last updated" that moves for cosmetic reasons leaves a reader unable to tell whether anything substantive changed, and leaves a machine unable to tell whether the page is current or merely rebuilt.
What the scanner actually checks
The rule is date-machine, worth 3 points in the freshness dimension. It looks for a machine-readable date in this order: dateModified, then datePublished, then article:modified_time. The first one found wins; the fields are not compared with each other. A date within twelve months is a full pass, an older date is a partial pass, an unparseable date is the minimum, and a page whose only date is the HTTP Last-Modified header gets a partial pass.
That precedence has a practical consequence: a page with a fresh datePublished and a stale dateModified is read as stale. If your content system bumps one and not the other, the older one wins. The fix is not to remove the field; it is to keep both truthful so the order does not matter.
The second freshness rule is copyright-year, worth 2 points. It looks for the current calendar year anywhere in the visible text. The rule page admits the weakness plainly: a site-wide footer that prints the current year lets an old page pass. That is a cheap check doing a cheap thing; adding the year to every page is not evidence that every page is current.
The failures that are easy to create and hard to notice
- The build-timestamp date.
dateModified = new Date()in a template moves the claim on every deploy. It is the most common way to make a date meaningless without lying in any single commit. - The orphaned pair. A new
datePublishedwith an olddateModified, or the reverse. Both are dates; only one is read. Keep them consistent. - Future dates. A timezone mistake or a manual entry can put a date ahead of the current time. A page cannot have been modified tomorrow; the claim is self-refuting.
- The footer year. A current copyright year on a page whose content is three years old passes the cheapest freshness check and misleads the reader.
- The reviewed/updated collapse. "Reviewed" can mean "read and confirmed"; "updated" means "changed". If the page was re-read but not changed, say reviewed; do not move the modified date.
- The single visible date. A human-readable date in the byline but no machine-readable date in the markup gives an engine less to work with than the page already displays.
An honest policy for a publishing schedule
The rule this site follows is simple enough to state in one paragraph: a page has a published date that never moves, an optional updated date that moves only when the page’s substance changes, and a sitemap lastmod that is a hand-maintained value checked by a test rather than new Date(). A new daily post therefore has a publication date and no updated date; an old post that gets a correction gets an updated date and keeps its original published date.
This is also why the blog byline shows "Updated" only when a revision happened. A field that always equals the publication date is not freshness information; it is decoration that trains a reader to ignore the field. The same standard applies to the structured data:dateModified uses the revision date when there is one, and the publication date otherwise.
How to check a page's dates
# 1. Extract the machine-readable dates from the server response
curl -sS https://your-domain.com/page/ \
| grep -oE '"(datePublished|dateModified)"\s*:\s*"[^"]+"'
# 2. Compare with the visible byline; they should agree
curl -sS https://your-domain.com/page/ | grep -oE '<time[^>]*>[^<]*</time>' | head
# 3. Reject a future date programmatically
curl -sS https://your-domain.com/page/ \
| python -c "import sys,re,datetime; html=sys.stdin.read(); \
dates=re.findall(r'\"(?:datePublished|dateModified)\"\s*:\s*\"([^\"]+)\"', html); \
[print(d, 'FUTURE' if datetime.datetime.fromisoformat(d.replace('Z','+00:00')) > datetime.datetime.now(datetime.timezone.utc) else 'ok') for d in dates]"The third check is worth putting in CI: a future date is a hard error, and a date that moves on a deploy with no content change is a review question. The first two are the ones a human can answer in a glance.
What dates do not decide
A recent date is not a ranking factor on its own, and an AI engine’s treatment of freshness varies and is not published. What the date does is give an engine something to reason with: whether the page is current, whether a cited figure is from this run or a previous one, whether an answer built from it is likely to still hold. That is a precondition for being read correctly, not a guarantee of being cited.
The smallest useful version is also the most durable: one publication date, one revision date that moves only when something changed, and a machine-readable copy of both. Everything else is a build pipeline pretending to be an editor.