SunExpress — homepage review — sample audit, scored 5.8/10

← gallery
5.8/10
Open ↗

About this audit

www.sunexpress.com scored 5.8/10

Correct where it counts, structurally slow — accessibility and consent are genuinely well built, but a client-rendered shell, a 12,147 ms LCP and a consent banner that covers the mobile booking widget hold it down. Homepage only — this score does not certify the booking funnel.

This is a full example audit — 11 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: 1,807,041 bytes of HTML deliver 114 characters of crawler-readable text — no H1, no JSON-LD.

What we found

  1. critical1,807,041 bytes of HTML deliver 114 characters of crawler-readable text — no H1, no JSON-LD

    Fetched without JavaScript, https://www.sunexpress.com/en-GB returns 1,807,041 bytes of HTML whose entire visible text content is 114 characters: Skip to main content plus the fare footnote *One-way-fare including service charge, fuel surcharge, taxes and fees. Limited availability. The raw document contains zero h1 el

  2. criticalThe Organization schema is an unfilled template — every field is an empty string

    The homepage serves exactly one JSON-LD block. It parses as valid JSON and declares "@type": "Organization", but every single value is empty: "name": "", "url": "", "logo": "", "telephone": "", a fully blank address object, and a sameAs array holding seven empty strings. The identical empty block is served on the Germa

  3. criticalLighthouse mobile 11 / 100 — LCP 12,147 ms, TBT 3,391 ms, interactive at 21,146 ms

    Lighthouse (mobile, lab) scores the homepage 11 / 100. LCP is 12,147 ms, Total Blocking Time 3,391 ms, Speed Index 8,492 ms and Time to Interactive 21,146 ms. The server itself is not the problem — server response is 257 ms; everything after that is client-side work on a 4,430 KiB page. The dominant cost is JavaScript

  4. warningCLS 0.444 — a single shift moves the whole page 24 px

    Lighthouse records a Cumulative Layout Shift of 0.444, well past the 0.1 threshold for a passing score. Measured live in the browser with a layout-shift PerformanceObserver, the cause is refreshingly narrow: one shift, at 628 ms, contributing 0.4054 of live CLS on its own. Its two sources are div.content-wrap moving fr

  5. warning447 KiB of oversized images — one 200 KB JPEG accounts for 173 KiB of it

    Lighthouse reports 447 KiB recoverable from properly sizing images, plus 173 KiB from next-gen formats and 140 KiB from re-encoding. The worst offenders are travel-requirements-760x556.webp (121,419 wasted bytes of 276,006), transfer-760x556.jpg (88,203 of 200,501), sxs-loyaltyshop-headers-911-x-495px-_webp.webp (84,53

  6. mobileThe consent banner covers 59.8% of the mobile viewport and sits on top of every booking control

    At 375 × 812 the OneTrust banner measures 356 × 511 px — 59.8% of the viewport — spanning y=150 to y=662 with position: fixed and z-index: 2147483645. It carries 186 words of body copy above its three buttons. This was checked properly rather than assumed. Using document.elementFromPoint() at the centre of each control

  7. mobileTrip-type toggles are 26 px tall — the smallest targets in the booking widget

    The One-way / Round trip / Multi-city toggles measure 82 × 26, 93 × 26 and 87 × 26 px (#OW, #RT, #MC, class .switch-button_item). Every other control in the widget is comfortable — From and To are 159 × 50, Search is 317 × 50 — so this is one inconsistent component rather than a systemic sizing problem. To be precise a

  8. warningNo og:image and no Twitter Card on any of the three locale homepages

    og:title, og:description and og:url are present, but og:image is absent, as are og:type and og:site_name. The entire twitter:* family — twitter:card, twitter:title, twitter:image, twitter:description — is missing. Verified across all three locale homepages: en-GB, de-DE and tr-TR are identically affected. Without og:im

  9. warningNo locale declares its own hreflang, and none declares x-default

    Each homepage lists the *other* two locales and omits itself. /en-gb/ declares de-DE and tr-TR; /de-de/ declares en-GB and tr-TR; /tr-tr/ declares en-GB and de-DE. No page declares x-default. Google's specification requires the set to be bidirectional and self-referential — each page in a cluster must include a tag poi

  10. warningThree security headers missing; HSTS max-age is 15,536,000 s short of the preload requirement

    Read live from the origin, the homepage sends content-security-policy: frame-ancestors 'self'; and strict-transport-security: max-age=16000000; includeSubDomains; preload;. Absent are X-Content-Type-Options, Referrer-Policy and Permissions-Policy. Two things are already right and should not be changed: frame-ancestors

  11. warning"Flight offers from Select country Select city" — a 149 px module that shows no offers

    The section heading is an h2 whose rendered text is literally Flight offers from Select country Select city — the two unset dropdown triggers are inside the heading element, so their placeholder labels are absorbed into it. That exact string is what the document outline exposes to screen readers and crawlers. The modul