The Weather Channel (weather.com) — site-wide review — sample audit, scored 5.4/10

← gallery
5.4/10
Open ↗

About this audit

weather.com scored 5.4/10

Solid engineering carrying a heavy ad stack. A 15,848 ms mobile LCP, ad and analytics vendors loading 1,273 ms before the consent dialog appears, and a primary nav tab that 404s outside the US are the ship-stoppers. Scope: 4 templates.

This is a full example audit — 16 evidence-led findings across accessibility, performance, SEO, structured data, privacy and security, each with a measurement, a screenshot and a concrete fix. The headline issue: The Allergies tab 404s for every non-US location — the other six nav tabs resolve.

What we found

  1. criticalThe Allergies tab 404s for every non-US location — the other six nav tabs resolve

    The forecast sub-navigation on the homepage renders seven tabs. Six return 200; Allergies returns a hard 404. Checked live against the same location ID the other tabs use: /weather/today/l/locality.490859236 → 200 /forecast/air-quality/l/locality.490859236 → 200 /forecast/allergy/l/locality.490859236 → 404 The location

  2. criticalAd and analytics vendors load at 347 ms — the consent dialog does not appear until 1,620 ms

    Measured live in the browser resource timeline on a first, uninteracted load of the homepage: 29 third-party hosts across 160 requests. The first ad-tech requests start at 347 ms — securepubads.g.doubleclick.net/tag/js/gpt.js, c.amazon-adsystem.com/aax2/apstag.js, micro.rubiconproject.com/prebid/dynamic/10738.js and cd

  3. criticalMobile homepage scores 16 / 100 — LCP 15,848 ms, TTI 20,220 ms, 752 KiB of unused JavaScript

    Lighthouse (mobile, lab) on https://weather.com/: Performance 16, Largest Contentful Paint 15,848 ms, First Contentful Paint 4,267 ms, Speed Index 7,009 ms, Total Blocking Time 1,908 ms, Time to Interactive 20,220 ms. Server response is 153 ms — the origin is fast. Everything after it is not. The single largest lever i

  4. criticalThe top ad slot reserves no height — a 298 px block drops in above the H1 and shoves the forecast down

    Lighthouse measures Cumulative Layout Shift on the mobile homepage at 0.318 — well past the 0.1 "good" threshold. The cause is one element. Measured live in the browser: the container matching .region-contentTop.adContainer sits at the very top of the content column and renders at 298 px tall with min-height: auto, no

  5. warningGrey-on-grey text fails WCAG AA at 2.96:1 and 3.31:1 — same .text-gray-400 token

    axe-core reports color-contrast (serious, WCAG 2.1 AA, criterion 1.4.3) on two templates, and both failures trace to the same Tailwind token. On /tr-TR, the ad labels: <div class="text-xxs ... text-gray-400">Advertisement</div> at #8d8d8d on #f2f2f2 — 2.96:1 at 10px, 2 elements. On the homepage footer: <p class="text-g

  6. warningThe "10 Day" nav link announces itself as "Close 10 Day"

    In the sidebar navigation, the 10-day forecast link contains an inline <svg><title>Close</title></svg>. Because an SVG <title> contributes to the accessible name, the link's computed name is Close 10 Day — verified live at 768 px on /storm-radar. A screen-reader user arrowing the main navigation hears a close/dismiss v

  7. warningNested interactive controls inside the SourcePoint consent dialog (2 elements)

    axe reports nested-interactive (serious, WCAG 2.0 A, criterion 4.1.2) with 2 failing elements, both inside #sp_message_iframe_898206 — the SourcePoint CMP. The offenders are an <h2 tabindex="0" role="button" aria-expanded="false" class="accordion"> and a <button class="pm-nswitch rejected pm-switch">, each carrying foc

  8. warningTwo <h1> elements on every content template, and section headings sit at the same level as their own items

    The homepage ships <h1>Kocakapı Weather</h1> and <h1>Daily Forecast</h1>; /tr-TR ships <h1>Ankara Hava durumu</h1> and <h1>Günlük Tahmin</h1>. Confirmed live on both. The location H1 is correct and should stay; Daily Forecast / Günlük Tahmin is a section label wearing an H1. The outline below it is inconsistent in a wa

  9. warningtwitter:card is summary_large_image with no image — homepage and /tr-TR share as bare links

    The homepage and /tr-TR both declare og:title, og:description, og:type and og:url, and twitter:card=summary_large_image — but og:image is null and twitter:image is null on both. A summary_large_image card with no image is a card that cannot render as designed; the two most-shared URLs on the site produce a text-only pr

  10. warning/storm-radar and /tr-TR/login describe themselves as WebSite; the homepage ships Organization twice

    All JSON-LD on the site parses cleanly — 0 invalid blocks across 4 templates, which is better than most sites this size. The problem is type selection. /storm-radar and /tr-TR/login each emit a block with "@type": "WebSite" carrying a page-level headline and description. WebSite describes an entire site, not a page; a

  11. warningThe Turkish page renders High, Low and Advertisement in English — while using the Turkish words elsewhere on the same page

    Verified against a cookie-free request to /tr-TR/tr/ankara/city/ankara/today with Accept-Language: tr-TR — so this is the server's own output, not a session artefact. In that HTML: >Advertisement< appears 3 times; >Reklam< appears 0 times. >High< and >Low< each appear once, inside the current-conditions card. Meanwhile

  12. warningReact hydration failures on two templates — the sign-in page abandons server HTML entirely

    The homepage logs React error #418 (hydration mismatch — the client-rendered UI did not match the server HTML). The sign-in page logs #418 five times and then React error #423, which is the escalation: *"Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering."* That l

  13. warningNo CSP, no Referrer-Policy, no Permissions-Policy — and the homepage is missing two headers its own subpages send

    Passive header observation across all four templates. Every page is HTTPS with HSTS present and no mixed content — the basics are right. Beyond that: Content-Security-Policy: absent on all 4. On a page assembling scripts from 29 third-party hosts, CSP is the control that limits what a compromised or swapped vendor scri

  14. warningA CORS failure on accounts.google.com/gsi/style fires on all four templates

    Every audited page, at every viewport, logs: Access to XMLHttpRequest at 'https://accounts.google.com/gsi/style' from origin 'https://weather.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. followed by Failed to load resource: net::ERR_FAILED. The Goog

  15. warningAn orphaned Weather Channel. paragraph sits in the footer of every page

    Directly beneath the ForecastWatch accuracy claim, the footer renders <p class="text-gray-400">Weather Channel.</p> — two words and a full stop, with no sentence around them. It is in the server-rendered HTML, so it is not a hydration artefact, and it appears on the homepage and the sign-in page, i.e. it is in the shar

  16. warningSign-in fields carry no autocomplete — password managers get no hint

    On /tr-TR/login, #loginEmail and #loginPassword both return autocomplete: null. Both fields do have proper <label> elements (E-posta, Parola) and required set, so the form is well built otherwise — this is one missing attribute pair. Without autocomplete="username" and autocomplete="current-password", browser autofill