Skip to content

Keep the canonical URL and og:url after the Notion client loads - #194

Merged
shigahi merged 1 commit into
masterfrom
client-canonical
Oct 28, 2026
Merged

shigahi merged 1 commit into
masterfrom
client-canonical

Conversation

@shigahi

@shigahi shigahi commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

Closes #193.

After it loads, the Notion client rewrites link[rel=canonical], og:url and twitter:url to its own relative /<Title>-<page-id> path, on every page. It adds a #block fragment after anchor clicks. The client script already kept the configured title and description after Notion changed them (applyMeta, #146). It now also keeps these three tags on the URL the worker chose:

Changes:

  • CLIENT_META gets origin: 'https://' + MY_DOMAIN. The value is passed as JSON instead of being written into the script as a string.
  • setContent takes the attribute to set, so it can also set href. It now updates every matching tag, not just the first, in case Notion adds a second one.
  • applyMeta computes the canonical path with the same rules as the server and sets the three tags.
  • The head MutationObserver also watches href changes.
  • The render check has a new canonical url check. In the browser, after the page loads, the canonical URL must be on the site's own origin and point to the root page, and og:url must resolve to the same URL.

Verification

  • npm test: 25 tests pass. This change is in the browser script, so it is covered by the render check and a Chromium comparison instead.

  • In wrangler dev against the live render check page, read in Chromium 10 s after load:

    Path Old worker New worker
    / /Worknot-Render-Check-<id> (relative) https://render-check.example.com
    /subpage /Render-Check-Subpage-<id> (relative) https://render-check.example.com/subpage
    /<item-id> (no slug) /Item-Beta-<id> (relative) https://render-check.example.com/<item-id>

    The values shown are for link[rel=canonical]. og:url and twitter:url had the same values in each case. The head had 0 attribute changes in the 3 s after the page settled, so the worker and the Notion client don't keep rewriting each other's values.

  • npm run check:render:

    • New worker: canonical url passes, and no check is FAIL.
    • Old worker: canonical url is FAIL (canonical: /Worknot-Render-Check-<id>#<block>). It passes on notion.site, so the check catches this regression.

Not tested: switching pages inside the Notion app. The subpage link on the test page doesn't load on notion.site either (the navigation checks are NOTION). The fix uses the same MutationObserver path as the title handling, which runs whenever Notion updates the head.

The Notion client rewrites link[rel=canonical], og:url and twitter:url
to its own relative /Title-<id> path after load, on every page. The
client script already restored the configured titles and descriptions;
it now also keeps these three tags on the URL the worker chose: the
slug for mapped pages, the page ID for pages without one.

The render check verifies this in the browser.

Closes #193

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shigahi
shigahi merged commit db62f19 into master Oct 28, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Notion client overwrites canonical URL and og:url in the browser

1 participant