The SkyCab is fifteen minutes from my house and I have taken visiting family up it more times than I can count. A few weeks ago I went looking for the ticket price on my phone and could not find it — not “could not find it easily”, could not find it at all.
So I spent a day measuring the site properly, from a browser, and then designed what I would build instead. Everything below is measured rather than estimated, and every figure is reproducible from a browser console in about a minute. No analytics access, no source code, nobody contacted.
Summary
One set of pages is serving two audiences, and the corporate one is winning.
Why this exists. I am a software engineer. I use the SkyCab, I looked at the website, and I found enough that I wanted to write it down properly rather than leave it as an opinion. Nothing here was commissioned and nothing is being pitched at the end of it. Everything is measured from the public site and reproducible in a browser, so any of it can be checked independently. If it is useful, use it — with or without me.
Panorama Langkawi operates one of Malaysia’s most recognisable attractions. The cable car holds a national record, the SkyBridge is on the front of half the postcards on the island, and the company holds a photography library most operators would envy. The opportunity this review identifies is that very little of that reaches the person deciding, on a phone, in a hotel room in Pantai Cenang, whether to come tomorrow.
The pattern running through the findings is that one set of pages is currently serving two very different audiences, and the corporate audience is winning. The newsroom is written for stakeholders. The trust badges — IAF, NIOSH, Standards Malaysia — are certifications that reassure an auditor rather than a family choosing a day out, and the newest customer-facing proof on the site is a TripAdvisor certificate from 2015. Meanwhile the task a visitor actually arrives to complete — find out what a ticket costs and buy one — is currently the hardest thing to do on the site.
The clearest example: no price on the site exists as text. Every figure is set inside a JPEG, and on the Promotion page the card layout crops those JPEGs so the prices are not merely unindexable, they are invisible to a reader as well. One consequence is that the official operator does not currently appear for its own highest-intent searches. Those visitors reach Klook, Traveloka and GetYourGuide instead, who resell the same seat and retain the commission. Recovering even part of that traffic is, in my view, the largest single opportunity here.
| Measure | Result | Note |
|---|---|---|
| Homepage weight | 26.5 MB | All ten photographs in the proposed redesign total 356 KB. |
| First Contentful Paint | 7.9 s | Google's "good" threshold is 1.8 s. Measured on fixed-line broadband. |
| One decorative PNG | 11.4 MB | A national-day flag overlay — 43% of the page, expiring in four days. |
| Contrast, every button | 2.36:1 | White on the brand blue. WCAG AA requires 4.5:1. |
| Prices readable as text | 0 | The Promotion page contains no "RM" anywhere in its markup. |
| Tap targets under 44 px | 37 / 43 | 86% of everything tappable on mobile is below the accessible minimum. |
| Booking domain | HTTP | No HTTPS redirect on the booking subdomain. A same-day configuration fix. |
| Languages served | 1 | A flag-dropdown language switcher whose only option is English. |
Method and scope
Measured from a browser against the live site, with no access to anything private.
Everything in this report was measured from a browser against the live
production site on 27 August 2026, at 1440 px desktop and 400 px mobile. Two
properties are in scope: the marketing site at panoramalangkawi.com and the
ticketing storefront at booking.panoramalangkawi.com.
Page weight, paint timing, request counts and asset sizes come from the browser’s own Performance API. Contrast ratios are computed from the rendered colours using the WCAG relative-luminance formula. Tap-target counts come from measuring the bounding box of every interactive element on the mobile layout. Heading order, link labels and alt-text coverage come from the live DOM.
I had no access to their analytics, their source code, their infrastructure or their commercial data. Nobody at Panorama Langkawi was contacted. Every claim below is either something I measured directly or something quoted from their own published pages; where a fact would have required their data, I have left it visibly blank rather than estimate it.
What the current site gets right
This is not a neglected site. Several of the genuinely hard parts are already solved.
It is worth being precise about this, because what follows is not the picture of a site nobody maintains.
The information architecture is genuinely complete. Every attraction has its own page. There is an operation calendar, a location map, a video gallery, visitor information, lost and found, a how-to-buy guide and a policy page. Plenty of larger operators have less.
The product naming system is excellent. SkyCab, SkyBridge, SkyGlide, SkyDome, SkyRex, SkyTrail, SkyBoutique, SkyBistro. A coherent, memorable family that scales to new attractions. This is real brand equity and the redesign keeps all of it.
The ticketing engine does hard things correctly. Timed slots with real capacity, nationality-tiered pricing, express-lane variants, combo products, a cart and customer accounts. Many attractions simply hand this to an OTA. Panorama built it.
They publish their downtime honestly. Weekly maintenance days and the SkyRex closure are stated prominently rather than hidden. That is operationally honest and unusually good practice — the problem is the format, not the candour.
The photography is outstanding. A large, well-shot library covering every attraction in good light. Every image in the redesign came from their own media folder. Nothing new was commissioned.
The server is fast. Time to first byte is 241 ms. The infrastructure is not the problem; the payload it is asked to deliver is.
They are measuring. GA4, Google Tag Manager, Microsoft Clarity and a Meta pixel are all installed. The instrumentation to prove or disprove everything in this report already exists.
The main site is on HTTPS and responsive. A valid certificate, a correct viewport meta, and a layout that adapts to phone widths without breaking horizontally. The fundamentals are in place.
The gap is not competence.
It is that the site’s content model treats operational facts — hours, closures, prices — as artwork rather than as data.
Where the journey loses people
Three layers: the findings that cost money, the ones that cost patience, and the craft.
The first ten seconds
Every visit opens on a full-screen image that must be dismissed before the site is reachable. On a phone it is taller than the screen. What it contains — today’s opening hours — is exactly what the page should be leading with, in the header, as text.
The prices are literally invisible
This is the single most consequential finding in the report, and it is best shown rather than described.
The booking domain does not enforce HTTPS. Requests to
booking.panoramalangkawi.com are not redirected to HTTPS, so the browser
treats the page as an insecure context. Because the booking form collects
contact details before payment, enabling a redirect and HSTS on that domain is
the highest-value quick win in this document, and it is independent of
everything else proposed here.
Prices are shown as ranges, never as a price. “RM33.00 – RM135.00” spans a Malaysian child to an international adult with Express Lane. The buyer cannot tell what they will pay until after they have filled in the form.
There is no total, anywhere, before commitment. The booking form asks for name, email, phone, nationality, date, time slot and four separate quantity fields — ten inputs — and then offers a “BOOK NOW” button. At no point does the page display what the booking costs.
Nationality silently sets the price. Malaysian and international rates differ by roughly 2×. The field that determines which you pay is an unexplained free-text box sitting between a phone number and a date.
The shop sells an attraction that is closed. The SkyCab product page promises “complimentary entrance to SkyDome, SkyRex and 3D Art Langkawi” while the homepage popup states SkyRex is closed until further notice. Both statements are live simultaneously, which is likely to produce refund requests and disputes at the counter.
One product carries three different names. “SkyCab Basic Package” on the
marketing site, “Normal Gondola” on the storefront, skycab-admission in the
URL. Separately, four premium gondolas priced from RM105 to RM550 share one
identical description, so the customer cannot tell what distinguishes them.
The most expensive product greets the buyer first. The storefront opens on “SPECIAL GONDOLA” at RM550. The standard adult ticket is eight cards further down the page.
Everything else that adds up
The language switcher offers one language. TranslatePress is installed and a flag dropdown renders in the header, but English is its only option. On mobile the white switcher box overlaps the utility bar and pushes the phone number off-screen entirely.
Eleven and a half screens of scrolling. The mobile homepage is 8,242 px tall against a 707 px viewport. Three feature cards each occupy a full screen before the visitor reaches anything purchasable.
No booking button on mobile. The primary revenue action is buried inside the hamburger menu. On desktop it is a dropdown styled identically to “The Company”, which contains careers and tender notices.
Thirty-seven links, four labels. “See more” appears 22 times, “Explore »” 8 times, “Buy Ticket” 4, “Explore” 3. A screen-reader user listing the links on the page hears “see more” twenty-two times in a row.
The H1 arrives thirty-eighth. The document emits 36 empty <h2> elements —
Elementor section wrappers — before the page’s only <h1>. Both crawlers and
assistive technology receive an inverted outline.
Every primary button fails contrast. White text on #01B3FF computes to
2.36:1. WCAG AA requires 4.5:1 for normal text. This is not one button — it is
the entire button system, sitewide.
Six of eight images have no alt text, and none are lazy-loaded. On a 26.5 MB page, nothing defers.
Two disconnected WordPress installs. The marketing site’s footer says © 2020; the storefront’s says © 2021. Different typography, different blue, different logo lockup, different footer — and the handoff between them happens at the exact moment of highest doubt, when the visitor is about to pay.
3.1 MB of video libraries on a page with no video. video.js (1.8 MB) and
videojs-vr.js (1.35 MB) load on every homepage visit. The homepage plays
nothing.
Staff webmail is linked from the public header. An icon beside the Facebook
and Instagram links points at mail.panoramalangkawi.com/owa, the staff
Outlook sign-in. Most likely a convenience shortcut that was never removed;
worth taking off the public header.
83 scripts and 67 stylesheets. 211 requests to render one screen — the accumulation typical of a long-lived WordPress and Elementor build, and the direct cause of the 7.9-second paint.
What was measured
Every figure taken from the live site, with the method beside it.
| Measure | Result | Benchmark | Source |
|---|---|---|---|
| Homepage transfer weight | 26.5 MB | — | Performance API, decoded body size across 211 requests |
| Largest single asset | 11.4 MB | — | merdeka-69.png, a CSS background, not lazy-loadable |
| First Contentful Paint | 7.9 s | < 1.8 s | Paint timing entry, fixed-line broadband |
| Time to first byte | 241 ms | < 800 ms | Navigation timing — the server is not the problem |
| Requests / scripts / stylesheets | 211 / 83 / 67 | — | Resource timing entries |
| Primary button contrast | 2.36:1 | ≥ 4.5:1 | WCAG relative luminance, white on #01B3FF |
| Tap targets below 44 px | 37 of 43 | 0 | Bounding boxes at 400 px viewport |
| Mobile homepage height | 8,242 px | — | 11.7 viewports at 707 px |
| Headings before the H1 | 36 | 0 | All empty <h2> section wrappers |
| Distinct link labels (37 links) | 4 | — | "See more" ×22, "Explore »" ×8, "Buy Ticket" ×4, "Explore" ×3 |
| Images missing alt text | 6 of 8 | 0 | Live DOM |
| Images lazy-loaded | 0 of 8 | — | Live DOM |
| Prices present as text | 0 | all | No "RM" string on /promo/; 911 chars of body copy |
| Languages in the switcher | 1 | — | Only en_US; hreflang lists en-US and en only |
| Booking domain transport | HTTP | HTTPS | No redirect configured on the booking subdomain |
| Storefront platform | WordPress 6.5.10 | — | Generator meta on the booking domain |
The pattern underneath
One early decision, never revisited, produces most of the list above.
Individually these read as a long list of separate defects. I do not think they are. They look like symptoms of one early decision that was reasonable at the time and has never been revisited: operational facts are handled as artwork rather than as data.
Opening hours are a poster. Closures are a poster. Prices are posters. Once that is true, most of the rest follows. A poster cannot be indexed, so the site loses the price searches. A poster cannot be translated, so the multilingual plugin sits idle. A poster cannot be read aloud, so screen-reader users get nothing. A poster cannot be updated without a designer, so the calendar is redrawn every month and a small spelling error in the current notice has persisted simply because correcting it means reopening the artwork. A poster has no idea SkyRex is closed, so the shop keeps selling it.
The second decision compounds it: the shop lives on a different WordPress install, on a different domain, with a different design and a different security posture. Nothing in the marketing site knows what the shop is selling, and nothing in the shop knows what the marketing site has promised.
Change the content model and roughly two-thirds of this list stops being possible, rather than being fixed one item at a time.
That is why the redesign below is not a reskin. The visual work is the visible part; the change underneath is that hours, closures and prices become records that drive the page, the structured data and the booking engine from one place.
The redesign
Five principles, and every photograph already in their media library.
They are stated first so that each design move below can be checked against one.
- The price is the product. Every figure becomes real text in a real table with structured data. This is the difference between owning “langkawi cable car ticket price” and renting that customer back from an OTA at commission.
- Decide before you disclose. The visitor sees a total before they give a name. Today’s funnel is inverted, which is why the form feels like an enquiry rather than a purchase.
- Operations belong in a database. Hours, closures and prices stop being artwork. This is what stops the site drifting stale the moment a project ends.
- One brand through payment. Merging two installs onto one HTTPS domain fixes the security problem and the trust problem in the same move.
- Keep the brand, fix the contract. The spiral, the wordmark, the Sky- product naming family and the SkyCab blue all stay. The blue simply stops being asked to carry white text at 2.36:1, a job it was never able to do.
All photography below is Panorama Langkawi’s own, taken from their media library. Nothing was commissioned and nothing was licensed.
What this fixes
The modal is gone. Its content moved into a permanent status bar: “Open now
· 9.30am–6.00pm today”, with the SkyRex closure beside it. Always visible,
always current, and readable by a crawler, a translator and a screen reader.
The same record emits openingHoursSpecification, so Google can show the real
hours in search.
“Book tickets” is a button, not a dropdown — one solid, high-contrast action in the header, distinct from everything else in the navigation.
The headline says something only this business can say. The geopark fact is genuinely Panorama’s, and every supporting figure is drawn from their own published pages: the Malaysia Book of Records span, six per cabin, three attractions included.
The price is knowable in the hero. Residency, date, slot and party size, with a running total — RM119 for two adults and a child — before anything personal is asked. The visitor never has to guess.
The photograph is the photograph. The 11.4 MB flag is deleted and the SkyBridge shot underneath it does the work it was taken to do.
[LIVE GOOGLE RATING]: it should be pulled live from Google rather than hard-coded, so it can never go stale.
What this fixes
Each product is described by what actually differs — who is in the cabin, whether you queue, what the floor is made of — rather than by an identical pipe-delimited feature list. A visitor can now tell a RM43 ticket from a RM550 one without phoning.
A price appears on every card, labelled with who it applies to (“Malaysian adult”, “Per cabin, up to 6”) instead of a range that applies to nobody.
What this fixes
Panorama sells considerably more than a cable car ride, but a first-time visitor would struggle to discover it. Eagle’s Nest SkyWalk — a steel walkway shaped as an eagle’s head, cantilevered over the ridge — is one of the most photographable structures on the island and currently appears as a line of text in a menu. Surfacing the wider estate visually looks like the cheapest available lever on average order value, since the combo tickets already exist.
What this fixes
This is the section that changes the search position. Every figure is selectable text: indexable by Google, translatable by the multilingual plugin, readable by a screen reader, and changeable by whoever sets prices rather than by a designer.
It also answers, in one glance, the question the current site never answers: what will I pay? Residency and age are columns rather than a hidden variable, and the rule that governs them — MyKad at the gate, children 3–12, under 3 free — is stated in words beside the numbers.
What this fixes
Every tap target is at least 44 px, enforced in the component library rather than left to chance — against 37 of 43 failing today.
The language control is real. Four languages with proper hreflang
alternates, which only becomes possible once the copy is text instead of JPEG.
For a destination whose visitors are heavily Malaysian, Chinese, Middle Eastern
and Indian, the current English-only dropdown is a straightforward loss.
The status line survives the mobile breakpoint instead of being covered by a floating switcher box.
The booking flow
Everything above is design. This is the part that changes revenue.
The five changes that matter
Price first, identity last. Nothing personal is requested until step two, after the visitor has decided. The current form collects name, email and phone before revealing a single number, which is why it behaves like an enquiry form rather than a shop.
A total that never leaves the screen. A sticky summary itemises the basket and shows what will be charged, updating as the visitor changes anything.
Residency becomes an explicit choice with a stated condition — “Malaysian rates need MyKad or MyPR at the gate” — rather than a free-text field that quietly doubles the bill.
Express Lane becomes an upsell, not a fourth ticket type. One checkbox sold against the real queue length, instead of four quantity boxes for a single decision.
Capacity is stated in human terms. “Plenty left”, “Only 12 seats” — not “(200)”.
And underneath
The two WordPress installs merge onto one HTTPS domain. The visitor never
leaves panoramalangkawi.com, the certificate is valid throughout, and the
brand does not change character at the moment of payment.
Marking SkyRex closed in the operations record removes it from every package description automatically, so the shop can never again sell an attraction that is shut.
The design system
Keep everything about the brand that works. Change only what is measurably broken.
The colour decision
The SkyCab blue #01B3FF is kept — it is the brand, and it is genuinely
distinctive. What changes is its job. At 2.36:1 against white it cannot legally
carry text, so it is reassigned to the things it is good at: rules, icons,
illustration, the cable line. A darkened version of the same hue, #0E78A8 at
4.92:1, takes over every button, link and interactive border.
That is the whole fix. Same brand, same hue family, one new token — and the entire button system moves from failing to passing.
What was deliberately not changed
The spiral mark, the wordmark, the Sky- product naming family, the company’s photography, the ticketing engine’s underlying logic (timed slots, residency tiers, express variants, combos), and the honest practice of publishing maintenance days. All of it is an asset. None of it is the problem.
Delivery
Most of the measurable win lands in week one, before any redesign ships.
A proposal that pretends otherwise is selling a redesign rather than solving a problem.
Week 1 · Stop the bleeding — Enable an HTTPS redirect and HSTS on the booking domain. Delete the 11.4 MB overlay and the two unused video libraries. Publish a plain-text price page. Remove the closed SkyRex from every package description. None of this requires a redesign, none of it touches the visual identity, and together it takes the homepage from 26.5 MB to roughly 1 MB and puts prices in front of Google for the first time.
Weeks 2–6 · The storefront — One domain, one design system, the three-step booking flow with a live total. Ship the checkout before the marketing pages: it is where the money is, and it is the smaller surface. The marketing site can keep running on its existing theme while this lands.
Weeks 7–12 · The content model — Operating calendar, closures and prices become structured records that feed the page, the schema markup and the booking engine from one place. This is the part that stops the site drifting stale again the moment the project ends — and it is the part most agency proposals leave out, because it is invisible in a mockup.
Targets
| Measure | Today | Target | How |
|---|---|---|---|
| Homepage weight | 26.5 MB | < 1.5 MB | Drop the overlay and video libraries; serve AVIF at real display sizes |
| First Contentful Paint | 7.9 s | < 1.8 s | 83 scripts and 67 stylesheets collapse to a static build with a booking island |
| Prices indexable | 0 | all | HTML table plus Product/Offer schema, generated from the price list |
| Button contrast | 2.36:1 | 4.92:1 | Same hue darkened to #0E78A8; brand blue retained for graphics |
| Tap targets under 44 px | 37 of 43 | 0 | Enforced minimum in the component library, checked in CI |
| Screens to a price on mobile | never | 0 | Persistent booking bar carries the running total from first paint |
| Booking domain transport | HTTP | HTTPS + HSTS | Same-day fix, independent of the redesign. Do this first. |
| Languages served | 1 | 4 + hreflang | Possible once the copy is text rather than JPEG |
What I would need before quoting
The problems above are measured, so I am confident about them. Sizing the fix needs three things only Panorama holds:
- Analytics access, and the current split between direct bookings and OTA bookings. That number decides whether the price-indexing work is worth six weeks or six months.
- Whether the booking engine is a licensed product or bespoke. If licensed, the merge onto one domain is a vendor conversation before it is an engineering one.
- Who owns the operating calendar today, and in what tool. The content-model work succeeds or fails on whether that person’s workflow gets easier.
Method notes and limitations
What the audit could not see, and where it corrected itself.
Bracketed text is deliberate. Several places in the mockups read
[LIVE GOOGLE RATING],[PEAK HOURS],[DRIVE TIME],[LIVE QUEUE TIME]or[CUT-OFF]. An earlier draft invented plausible values for these — drive times, queue lengths, “clearest views before 11am”. They were removed. A designer’s guess about operating conditions is exactly the kind of content that should come from an operations record, and inventing it would have undermined the report’s central argument.
This report was reviewed against itself, and it found errors. Four of the six contrast ratios on the first draft of the design-system sheet were computed against white instead of against the text colour actually placed on each swatch. They are corrected here. The two figures the argument rests on — their 2.36:1 and the proposed 4.92:1 — were right in both drafts.
The same pass caught the draft violating its own contrast rule in three places, including a “Sold out” state at 1.71:1, and a claim that the flag PNG was “larger than the rest of the page combined” when it is 43% of it. All corrected. A document that audits someone else’s contrast has no business failing its own.
Prices are theirs, reproduced for illustration. RM43 / RM33 Malaysian and RM85 / RM65 international for standard SkyCab admission, and the combo and Express Lane figures, are the rates published on panoramalangkawi.com on 27 August 2026. They are shown to demonstrate the layout, not to assert what Panorama should charge.
Photography is theirs. All ten images in the redesign were taken from Panorama Langkawi’s own media library and downsampled. They are used here to show what their existing assets can look like when they are prepared properly. Any real engagement would use the originals.
What this audit could not see. No analytics, no server logs, no source code, no conversion data, no commercial terms with OTAs, no view of the admin experience for the staff who maintain the site. Several conclusions — particularly about direct bookings lost to resellers — are mechanically sound but cannot be quantified without that access, and I have deliberately not estimated them. This review was prepared independently and was not commissioned.
One number worth remembering
All ten photographs in the redesign total 356 KB. The current homepage’s single seasonal overlay is 11.4 MB — thirty-two times as much. Same island, same photographs, same company. The whole difference is in how the files are prepared and served, which is a solvable problem and a fast one.
Panorama Langkawi · product and front-end audit · 27 August 2026
An independent review of a live public website, conducted from the browser and not commissioned. All trademarks and photographs remain the property of Panorama Langkawi Sdn Bhd and are reproduced here only to illustrate the proposal.