Skip to content

Technical SEO - Fix og:image dimensions, hreflang dedupe + x-default, html lang#1377

Open
slightlyoffbeat wants to merge 1 commit into
mainfrom
techseo-template-head
Open

Technical SEO - Fix og:image dimensions, hreflang dedupe + x-default, html lang#1377
slightlyoffbeat wants to merge 1 commit into
mainfrom
techseo-template-head

Conversation

@slightlyoffbeat

@slightlyoffbeat slightlyoffbeat commented May 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Four small head-metadata fixes batched into one PR (A6 b–d in the firefox.com technical SEO master plan):

  1. og:image:width and og:image:height added — improves how shared firefox.com links render in social previews (LinkedIn, Slack, X, iMessage, Discord, etc.) by declaring image dimensions upfront.
  2. Duplicate hreflang="en" removed — en-US pages were declaring both hreflang="en" and hreflang="en-US"; the bare en overlaps with en-US and creates a redundant signal to Google. Dropped the duplicate.
  3. x-default extended to all pages — was previously homepage-only; now emitted on every page so users in unsupported locales reach the right fallback regardless of which URL they hit directly.
  4. <html lang> attribute corrected for en-US — was emitting lang="en" due to a |replace('en-US', 'en') filter; now emits lang="en-US" to match the actual locale and improve screen-reader pronunciation.

All four are zero-visual-change improvements to SEO, social-sharing, and accessibility signals. No change to user-visible firefox.com behavior. No CSS, JS, or layout impact.

Why

  • Search engines route locales more accurately (deduplicated hreflang signal, x-default everywhere)
  • Social platforms render shared links better (image dimensions declared upfront, no re-fetch needed)
  • Screen readers pick a more accurate pronunciation engine on en-US pages

What changed

springfield/cms/templates/cms/base-flare26.html

  • Line 10: lang="{{ LANG|replace('en-US', 'en') }}"lang="{{ LANG }}"
  • Line 52 area: Added two new {% block %} slots emitting dimensions adjacent to the existing og:image tag:
    • {% block page_image_width %} defaults to {{ img.width }} for CMS pages with a custom og_image, otherwise 1200
    • {% block page_image_height %} defaults to {{ img.height }} for CMS pages with a custom og_image, otherwise 630
    • Default og.png is confirmed 1200×630, matching the hardcoded fallback values

springfield/base/templates/includes/canonical-url.html

  • Removed the {% if is_homepage %}...{% endif %} wrapper around the x-default emission so it fires on every page
  • Removed the redundant <link rel="alternate" hreflang="en" ...> line in the en-US locale block; only hreflang="en-US" remains

springfield/cms/tests/test_locale_fallback_rendering.py

  • Updated assertion at lines 481–483 to reflect the new behavior: was checking that en-US pages emit both hreflang="en" AND hreflang="en-US"; now asserts hreflang="en" is not present and hreflang="en-US" IS present. Comment updated.

Scope notes

  • Other base templates (base-flare.html, base-protocol.html) intentionally not updated — they're being sunset and still use the |replace('en-US', 'en') filter. Pages extending those bases continue to emit lang="en" on en-US locales for now. Known transitional state.
  • ~20 hand-rolled templates override {% block page_image %} with non-1200×630 images (firefox/features/fast.html, firefox/browsers/compare/chrome.html, various landing pages, etc.). They'll get the hardcoded 1200×630 default for width/height. Social platforms fall back to fetching the image and reading real dimensions when declared values don't match — wrong values don't break previews, just less optimal. Templates can opt into accurate dimensions by overriding the new page_image_width / page_image_height blocks when next touched. Accepted trade-off.

Fallback behavior preserved

Removing hreflang="en" does not remove fallback. The two mechanisms are:

  • English speakers outside US (en-GB, en-CA, en-AU, en-IN, etc.) — Google's hreflang algorithm uses language-match before region-match, so they still resolve to the en-US page via hreflang="en-US" as the closest English variant.
  • Users in unsupported languages entirely (no matching hreflang) — x-default points to the unprefixed canonical URL, which hits the locale-negotiation middleware and routes them to the closest supported locale via Accept-Language. This used to be homepage-only; now sitewide. Fallback strengthened, not removed.

Audit / review

Performed a thorough code audit for unintended side effects. Findings:

  • No CSS :lang() selectors anywhere in the codebase (confirmed via grep)
  • Only one JS file reads document.documentElement.lang for value (media/js/firefox/features/translate.es6.js) — uses it with Intl.DisplayNames, which handles both "en" and "en-US" identically for English display. No behavior change.
  • Other JS that touches <html> (sentry-consent, stub-attribution, gtm-snippet, etc.) reads data-attributes or manipulates classList, not lang. No impact.
  • Newsletter form's lang hidden input (newsletter_form.html:53-54) and corresponding test (test_pages.py:320) operate on the Python LANG template variable, not on the HTML attribute. Unchanged behavior — LANG.startswith('en-') still evaluates correctly.
  • Static error pages (403_csrf.html, cron-health-check.html) have hardcoded <html lang="en"> and don't use LANG — unaffected.
  • No middleware, l10n_utils, redirect, or analytics code branches on hreflang or <html lang> value.

Test results

Ran the full affected test suites locally:

  • springfield/cms/tests/test_locale_fallback_rendering.py21/21 pass (includes the updated assertion)
  • springfield/cms/tests/652/656 pass (4 failures pre-existing in BootstrapLocalAdminTests, unrelated to A6 — bootstrap_local_admin command leaking from local .env)
  • springfield/firefox/tests/531/531 pass

Zero regressions introduced by A6.

Manual test plan

  • Run the updated test: pytest springfield/cms/tests/test_locale_fallback_rendering.py -v → passes
  • View source on en-US homepage → <html lang="en-US">, og:image:width="1200", og:image:height="630", single hreflang="en-US" entry (no hreflang="en"), x-default present
  • View source on a non-homepage en-US CMS page → x-default present (was previously homepage-only)
  • View source on a CMS page with a custom og_imageog:image:width and og:image:height reflect the actual rendition dimensions
  • View source on a hand-rolled template overriding page_image (e.g. /firefox/features/fast/) → emits default 1200×630 (accepted trade-off)
  • View source on a non-English page (e.g. /fr/, /pt-BR/) → <html lang="fr">, <html lang="pt-BR"> unchanged
  • Paste rendered HTML into Facebook Sharing Debugger or LinkedIn Post Inspector after deploy to stage → link preview renders correctly with declared dimensions

@slightlyoffbeat slightlyoffbeat added the SEO The outcome of this work is primarily for SEO purposes. label May 22, 2026
@janriokrause

Copy link
Copy Markdown
Contributor

View source on a CMS page with a custom og_image → og:image:width and og:image:height reflect the actual rendition dimensions

I'm checking http://localhost:8000/en-US/compare/chrome/ which already had a custom og_image. But I cannot see any og:image:width or og:image:height.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR batches several small, head-metadata updates to improve firefox.com technical SEO signals, social preview rendering, and accessibility language metadata for en-US pages.

Changes:

  • Emit correct <html lang="{{ LANG }}"> for en-US (stop rewriting en-USen).
  • Add og:image:width / og:image:height alongside the existing og:image tag in base-flare26.html.
  • Deduplicate hreflang="en" for en-US and emit hreflang="x-default" on all pages (not homepage-only), with a corresponding test assertion update.

Review notes (per repo custom Copilot instructions):

  • Two non-blocking suggestions were left: (1) avoid repeating the image(..., "width-1200") rendition lookup 3x in the same template render, and (2) add a test assertion for the new sitewide x-default output to reduce regression risk.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
springfield/cms/templates/cms/base-flare26.html Fixes html[lang] for en-US and adds Open Graph image dimensions.
springfield/base/templates/includes/canonical-url.html Emits x-default sitewide and removes redundant hreflang="en" for en-US.
springfield/cms/tests/test_locale_fallback_rendering.py Updates hreflang assertions for the en-US dedupe behavior.

Comment on lines 51 to +54
<meta property="og:url" content="{% filter trim|absolute_url %}{% block page_og_url %}{{ settings.CANONICAL_URL + '/' + LANG + canonical_path }}{% endblock %}{% endfilter %}">
<meta property="og:image" content="{% filter trim|absolute_url %}{% block page_image %}{% if page and page.og_image %}{% set img = image(page.og_image, "width-1200") %}{{ img.url }}{% else %}{{ static('img/firefox/flare/og.png') }}{% endif %}{% endblock %}{% endfilter %}">
<meta property="og:image:width" content="{% block page_image_width %}{% if page and page.og_image %}{% set img = image(page.og_image, "width-1200") %}{{ img.width }}{% else %}1200{% endif %}{% endblock %}">
<meta property="og:image:height" content="{% block page_image_height %}{% if page and page.og_image %}{% set img = image(page.og_image, "width-1200") %}{{ img.height }}{% else %}630{% endif %}{% endblock %}">
Comment on lines 479 to 483
assert f'rel="canonical" href="{settings.CANONICAL_URL}/en-US{page_path}"' in html
assert '<meta name="robots" content="noindex,follow">' not in html
# en-US should emit both hreflang="en" and hreflang="en-US".
assert f'hreflang="en" href="{settings.CANONICAL_URL}/en-US{page_path}"' in html
# en-US should emit hreflang="en-US" only (duplicate bare hreflang="en" was removed for SEO clarity).
assert f'hreflang="en" href="{settings.CANONICAL_URL}/en-US{page_path}"' not in html
assert f'hreflang="en-US" href="{settings.CANONICAL_URL}/en-US{page_path}"' in html
@janriokrause

Copy link
Copy Markdown
Contributor

I ticked off most of the manual test plan.

Also, just pushed the branch to fxc-demo-5, live in a few minutes at https://www-demo5.springfield.moz.works/, to check the Facebook Sharing Debugger and LinkedIn Post Inspector. They unfortunately don't accept HTML input, but URLs only.

@maureenlholland maureenlholland removed their request for review June 11, 2026 16:18
@maureenlholland

Copy link
Copy Markdown
Collaborator

Removing myself as reviewer as I don't have the expertise to add anything to the current reviews.
I also don't have Facebook or LinkedIn accounts and cannot verify the demo5 behaviour

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

SEO The outcome of this work is primarily for SEO purposes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants