62 · SEO + perf audit, 2026-05-19
Scope: insiders-trades.com (prod), full SEO + perf audit, plus action-pack of low-effort wins shipped same day.
TL;DR
- Lighthouse SEO 100/100 on / mobile and desktop (already at ceiling pre-fix).
- Structured data complete: Organization + WebSite + SearchAction on every page, plus Article + BreadcrumbList on blog posts, Organization + BreadcrumbList on /company/
/. - Sitemap healthy, robots clean, hreflang in HTML (case-sensitive grep miss earlier).
- Top wins shipped this round: trim oversize meta description on home (433 -> 155 chars), add OG image to all top routes (21 metadata builders patched), fix /companies/ title that was truncating mid-comma in SERPs, normalize brand string ("InsiderTrades" -> "Insiders Trades Sigma") on /methodologie/.
Lighthouse (prod)
| Route | Device | SEO | Best Pract. | A11y | Agentic |
|---|---|---|---|---|---|
| / | mobile | 100 | 96 | 92 | 33 |
| / | desktop | 100 | 96 | 92 | 67 |
Six failed audits, all pre-existing, none blocking SEO score:
- errors-in-console: 3rd-party network errors (GTM beacons, ignore).
- aria-prohibited-attr: 1 element, low impact.
- aria-required-children: 1 element, ditto.
- label-content-name-mismatch: visible-vs-AT label drift on one CTA.
- agent-accessibility-tree: agentic-browsing category, not user-facing SEO.
- llms-txt: false positive (file has H1; Lighthouse heuristic flake).
Perf (LCP/INP/CLS) not measured via lighthouse_audit MCP wrapper (perf category not exposed). Field data should be pulled via skill seo-google (CrUX) for the real number.
Audit findings (before fixes)
Metadata
| Route | Title len | Desc len | OG image | Status |
|---|---|---|---|---|
| / | 74 | 433 (FR) | missing | description way over 160 char SERP cutoff |
| /performance/ | 55 | 211 | missing | desc slightly long |
| /methodologie/ | 34 | 216 | missing | desc slightly long, brand "InsiderTrades" inconsistent |
| /companies/ | 67 (cut at "RNS") | 184 | missing | title truncated mid-list |
| /insiders/ | 33 | 231 | missing | desc slightly long |
| /how-it-works/ | 37 | 158 | missing | ok except no OG image |
| /pricing/ | 70 | 158 | present (root fallback) | ok |
| /blog/ | 60 | 167 | missing | ok except no OG image |
| /about/ | 30 | 178 | present (root fallback) | ok |
Root cause for missing OG: every page-level generateMetadata sets openGraph: { url, locale }, which fully shallow-overrides the root layout's openGraph object (Next.js merges by top key, not deep-merge). The 21 metadata builders dropped the images array.
Sitemap
/sitemap.xmlreturns 200 with sitemap-index (8 sub-sitemaps).- All canonical routes listed: static EN/FR, blog EN/FR, companies (14M XML), insiders, landings, docs.
lastmodaccurate (2026-05-19).- Listed in robots.
Structured data (validated by grep + spot-check)
- Homepage:
@graphwith Organization (+founder Person) and WebSite (+SearchAction). 2 LD-JSON nodes. - /company/
/: 7 @types (Organization, BreadcrumbList, ListItem, WebSite, Person, SearchAction, EntryPoint). - Blog article: 8 @types including Article + BreadcrumbList.
- All emit on first paint (server-rendered).
hreflang
Present on every route (en, fr, x-default). Self-canonical correct. No trailing-slash drift detected.
robots.txt
Clean: index/follow defaults, explicit allowlist for canonical routes, disallow on /api/, /admin/, /auth/, /account/, /portfolio/, /recommendations/, /_next/, /en/. Blocks GPTBot, CCBot, anthropic-ai, Google-Extended.
GSC + GTM
GSC verification meta present in root layout. GTM container GTM-TT9CK3WB loaded. Consent Mode v2 default state set before GTM bootstrap, with geo-aware EU/EEA/UK/CH default-denied. GA4 (G-W1YPTBW2PT) fires from inside the container.
Fixes shipped (this commit)
- Home description trimmed from 360+ chars to ~155 chars (FR + EN).
- OG image (
/logo-mark.png, 512x323) now declared on all 21 page-level metadata blocks via a singlesiteName + imagesinjection (sed replace on the shared pattern). - /companies/ title scope tightened from 17-regulator inline list to "covered across 28 markets" / "couverts sur 28 marchés"; full regulator list moved into description only.
- /methodologie/ brand string normalized to "Insiders Trades Sigma" (was the legacy "InsiderTrades").
Files touched:
- src/app/page.tsx
- src/app/companies/_shared.tsx
- src/app/methodologie/page.tsx
- 19 other page.tsx and _shared.tsx files (OG image injection only)
Validation:
- tsc: clean
- lint:emdash: clean
- lint:emoji: clean
- npm run lint: 128 pre-existing warnings/errors unrelated to this diff
Top 10 next-step recos
- Dedicated OG image generator: build
src/app/api/og/route.tsxwithnext/ogImageResponse. Current fallback (/logo-mark.png) is 512x323, below Twitter's recommended 1200x630. Per-route OG with title + KPIs would lift CTR meaningfully on social and AI Overviews. - CrUX field data: pull real LCP/INP/CLS for top 10 routes via PageSpeed Insights API (skill seo-google). Lighthouse lab numbers are not the ranking signal.
- Image audit: run
npm runagainst/public/**to find PNGs >100 KB.logo-mark.pngis 102 KB; convert the masters to WebP/AVIF, keep PNG as fallback only. - Description trim sweep: /performance/ (211), /methodologie/ (216), /insiders/ (231) descriptions still over the 160 SERP cutoff. Quick win pass-2.
- Internal mesh on /company/
/ : add "Other companies in" links (already partly present), plus "Top insiders for this issuer" cards linking to /insider/ /. Builds the hub-and-spoke topology that pulls long-tail rankings. - Breadcrumb on listing hubs: /companies/, /insiders/, /companies/by-sector/
/ should emit BreadcrumbList JSON-LD (currently only individual entity pages have it). - Article schema author: /blog/ Article LD-JSON should reference
Personwith sameAs (LinkedIn, X) to lift E-E-A-T for AI Overviews. Currently onlyOrganizationpublisher. - Trailing-slash audit: confirm 301 chain
/foo->/foo/is single-hop (no/foo->/foo/-> canonical query strip). Run a quickcurl -sIsweep on top 20 routes. - CSP header: currently
content-security-policy-report-only. Promote to enforced once GTM + Vercel + Stripe origins are confirmed in 2 weeks of reports. - llms.txt verbosity: current
/llms.txtis 4.5 KB Markdown. Lighthouse flagged it (false positive). Add an explicit# Insiders Trades SigmaH1 in the very first line position (it is, but a leading byte-order mark or whitespace might be confusing the scanner). Worth a 5-min recheck.
Validation block (post-commit, pre-deploy)
Run deploy-guard + prod-healthcheck after push to confirm.