风 冷气服务Kaze Aircon Services
Air-con servicing, 60 technicians · Singapore · Singapore
Case study · Technical SEO · 5 months
A JavaScript booking app was hiding Singapore's busiest aircon servicer from Google
A client-rendered single-page booking site meant Google saw almost empty pages, so service and estate pages never indexed.
请到柜台Now serving
Indexed pagescounter 05
Issues fixed
- ●NOW SERVINGA01 fixed · first HTML now carries 14 KB of content
- ●NOW SERVINGA02 fixed · 46 estates on real URLs
- ●NOW SERVINGA03 fixed · 2,640 slot URLs out of the crawl
- ●NOW SERVINGA04 fixed · mobile LCP 1.8 s
- ●NOW SERVINGA05 fixed · prices readable as text
- ●NOW SERVINGA06 fixed · one phone format everywhere
The busiest counter in Singapore, and Google could not see the queue.
A client-rendered single-page booking site meant Google saw almost empty pages, so service and estate pages never indexed.
Kaze Aircon Services runs 60 technicians across the island and takes most bookings online. The site was a single-page app: lovely to use, but every service and estate page was assembled in the browser. Googlebot fetched each URL, found an empty shell and moved on. Of roughly 460 pages a customer could reach, 38 were indexed.
The work was never about more content. It was about letting Google read what was already there.
What Googlebot got
<html> <head> <title>Kaze Aircon</title> </head> <body> <div id="app"></div> <script src="/main.js"> </body> </html>
1.1 KB. No services, no prices, no estates.
What customers got
- General servicing · $30/unit
- Chemical wash · $60/unit
- Gas top-up · from $50
- 46 estates, same-week slots
Rendered after 3 API calls and 1.4 MB of JavaScript.
Seven tickets in the queue, numbered by severity.
- A01Critical
Rendering
Googlebot received a 1.1 KB shell
The first HTML response was a single empty <div id="app">. Service copy, prices and estate names arrived after three API calls and a 1.4 MB bundle, so most pages were queued for rendering and dropped as soft-empty.
- A02Critical
Rendering
Hash-routed URLs
Estate pages lived at /#/estates/tampines. Google ignores the fragment, so 46 estate pages collapsed into one URL: the homepage.
- A03High
Index bloat
2,640 booking-slot URLs
Every calendar slot (?date=…&slot=…) was a crawlable link. Googlebot spent most of its visits on empty calendars instead of service pages.
- A04High
Core Web Vitals
Mobile LCP 5.2 s, INP 410 ms
The hero image was requested by JavaScript after hydration; a chat widget and three analytics tags blocked the main thread on mid-range Android phones.
- A05Medium
Schema
No structured data, prices in images
No HVACBusiness, Service or Offer markup. The price list was a PNG, so 'chemical wash price' queries had nothing to match.
- A06Medium
Local
Profile linked to the booking subdomain
The Business Profile pointed at book.kaze… with a different phone format from three directories, splitting local signals.
- A07Medium
Content
Swapped-name estate templates
The estate pages that did render were identical apart from the estate name: no block types, travel times or typical unit brands.
Four stalls, one queue.
Built on our Signal plan (Technical SEO). Fix what Google receives first, then make it fast, then stop it wasting visits, then describe every page in machine-readable terms.
JavaScript rendering
Service, price and estate pages pre-rendered at build time, so the first byte carries the content.
- Moved routes from hash to real paths with 301s
- Static generation for 9 services × 46 estates
- Booking calendar kept client-side, behind one button
Core Web Vitals
The page paints before the booking app wakes up.
- Hero image preloaded and served as AVIF
- Bundle split: 1.4 MB → 380 KB on first load
- Chat and tags deferred until interaction
Index bloat
Crawl budget returned to pages a customer could actually land on.
- Slot and date parameters made non-crawlable
- Canonicals and noindex on 2,640 calendar URLs
- Sitemaps split by service, estate and guide
Schema markup
Machine-readable facts for every service and area served.
- HVACBusiness with areaServed per estate
- Service + Offer with per-unit prices as text
- FAQ markup on wash, gas top-up and leak pages
5 months on the board.
M1
诊断
Raw vs rendered
Crawled the site twice, with and without JavaScript, and diffed every page. Mapped 2,640 slot URLs and 46 hash-routed estates.
Indexed
61
M2
渲染
Pre-rendering ships
Real URLs with 301s from the old fragments. Service and estate pages now arrive as complete HTML; the booking app hydrates only the calendar.
Indexed
142
M3
清理
Crawl budget back
Calendar parameters blocked and canonicalised. Googlebot's daily fetches shift from empty slots to service pages within three weeks.
Indexed
268
M4
速度
Speed and schema
Bundle split, hero preloaded, tags deferred. HVACBusiness, Service and Offer markup on every page; price list rebuilt as text.
Indexed
362
M5
巩固
Estate hub
Estate pages rewritten with block types and travel times, linked from a Singapore coverage hub. Profile and directories aligned.
Indexed
410
Every number, called to the counter.
叫号 · Now serving · ticket 001
Organic sessions
- 001 Organic sessions
- +147%
- 002 Online bookings from organic
- +92%
- 003 LCP (mobile)
- 5.2s → 1.8s
Modelled scenario for a fictional business — not a client result. Rankings and traffic are never guaranteed; see our Terms.
Indexed pages · one LED ≈ 20 pages
Organic sessions per month
Online bookings from organic
LCP (mobile), 75th percentile
Green zone: under 2.5 s counts as good.
Before · month 0
kazeaircon.sg › #
Kaze Aircon | Loading…
You need to enable JavaScript to run this app.
After · month 5
kazeaircon.sg › services › chemical-wash
Aircon Chemical Wash Singapore · from $60/unit | Kaze
Same-week chemical wash for wall-mounted and cassette units across 46 estates. Gas top-up, leak repair and general servicing, priced per unit.
Rankings board
Modelled Google positions in Singapore, before the work and at month 5.
| Query | Monthly searches | Before | Month 5 |
|---|---|---|---|
| aircon servicing singaporeService | 9,900 | not indexed | #4 |
| aircon chemical washService | 4,400 | 41 | #3 |
| aircon gas top up priceService | 1,900 | not indexed | #2 |
| aircon water leakingService | 2,400 | 67 | #5 |
| aircon general servicing priceService | 1,300 | 28 | #1 |
| aircon servicing tampinesEstate | 880 | not indexed | #1 |
| aircon servicing jurong westEstate | 720 | not indexed | #2 |
| aircon servicing bedokEstate | 590 | not indexed | #3 |
| aircon repair woodlandsEstate | 480 | not indexed | #2 |
| condo aircon servicing punggolEstate | 320 | not indexed | #1 |
下一位 · Next in line
Get a plan like this
If your site is built in JavaScript and Google is not seeing it, Signal starts with a raw-versus-rendered crawl of every page.