How to make Bubble site visible to search crawlers

We rebuilt our clinic’s website on Bubble earlier this year. .

Then our organic traffic fell off a cliff.

If you’re a Bubble developer who’s hit the same wall, this post is for you. Here’s exactly what was wrong, why it’s easy to miss, and how we fixed it without Bubble’s dedicated-server plan.

The symptom: “no outgoing links,” “orphan page,” on hundreds of pages at once, ahrefs shows bad health across the whole site.

Running an Ahrefs Site Audit, we saw the same handful of issues repeated across roughly 360 pages simultaneously:

  • H1 tag missing or empty
  • Low word count
  • Page has no outgoing links
  • Orphan page (no incoming internal links)

The confusing part: these were all different checks, on completely different topics (headings, word count, outbound links, inbound links) — yet they were failing on the exact same set of pages, every time. That pattern was the clue, though it took us a while to read it correctly.

We knew our internal linking was solid. We could see it, click through it, use it every day. So why did every crawler we tested — Ahrefs, and eventually confirmed via raw curl requests spoofing Googlebot and GPTBot — see a page with no headline, almost no text, and no links at all?

The actual cause: Bubble renders everything client-side

Bubble builds pages using JavaScript that runs in the browser. A human visitor’s browser executes that JavaScript and paints the full page. A crawler that doesn’t execute JavaScript — which includes most non-Google crawlers, and even Google itself on its first, faster crawl pass — receives only the raw, pre-JavaScript HTML: an empty shell of <script> tags with no visible content.

We confirmed this directly with a simple test anyone can run:

curl -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" https://yoursite.com/

If your actual page content — headlines, body text, links — doesn’t appear anywhere in that output, you have this exact problem.

A second, compounding issue: our navigation used Bubble’s Button element with “Navigate to page” workflows, rather than the actual Link element. Buttons with workflow-based navigation never produce a real <a href="..."> tag in the HTML — so even once content is visible, crawlers still can’t follow those links to discover other pages.

Dead end #1: Prerender.io + Cloudflare Worker

This is the standard, well-documented fix for this exact problem — a service that renders your page once, caches the result, and serves that cached HTML to bots while real visitors get the full interactive site. The catch: it requires proxying your domain through Cloudflare, and doing so makes Cloudflare inject IPv6 (AAAA) records. Bubble’s own SSL certificate validator flags any AAAA record as unsafe and throws a “bad DNS records” error — an unsupported configuration on anything short of Bubble’s dedicated-server tier. We spent a genuinely long, methodical session confirming this conflict from every angle — DNS, Workers Routes, live log streams, curl tests with multiple bot user-agents — before accepting it wasn’t going to work cleanly on a standard plan.

Dead end #2: a third-party “Bubble SEO” tool

We tried a new, third-party service (FastPages.live) promising to solve this exact problem via a similar Cloudflare-based approach, with genuinely impressive PageSpeed and Lighthouse improvements after connecting it. But a raw curl test — bypassing the browser entirely — showed it was never actually intercepting bot traffic; the visible speed gains were real, but came from CDN caching, not from solving the crawlability problem at all. Lighthouse and PageSpeed both execute JavaScript when they test, so neither tool ever revealed the gap. If you’re evaluating any similar tool, don’t trust the dashboard or the Lighthouse score — verify with curl and a spoofed bot user-agent directly.

What finally worked: build the snapshot pipeline ourselves, and route humans to the real thing

Once we accepted that any live, request-time interception in front of Bubble’s own domain was a losing fight, the actual fix became two separate, much simpler pieces:

1. Move the real Bubble app to its own subdomain. app.yoursite.com stays connected to Bubble exactly the normal way — plain DNS, no proxy, nothing for Bubble’s SSL validator to object to, ever.

2. Free the root domain up entirely, and put a static snapshot pipeline there instead.

  • A Node.js + Playwright script reads the site’s sitemap, visits every real URL with a headless browser, waits for it to fully render, strips out all the JavaScript (bots never execute it anyway, so it’s dead weight), and saves the resulting clean HTML.
  • That script runs automatically, on a schedule, for free, via GitHub Actions — no server to maintain, no minute limits on a public repo.
  • The output gets committed to a GitHub repo connected to Cloudflare Pages, which auto-deploys the moment new content lands.
  • The root domain’s DNS points straight at that Cloudflare Pages project.

3. A Cloudflare Worker sits in front of the root domain and makes one decision per request: bot user-agent → serve the static snapshot. Anything else → quietly proxy the request through to the real, live app. subdomain and return it under the main domain’s URL — so a human visitor never sees a subdomain, never sees a stripped-down page, and gets the exact same interactive site as always.

The result: crawlers get instant, fully-rendered HTML with zero JavaScript wait. Real visitors get the full, unmodified, interactive Bubble app. Nobody has to choose between the two.

Total cost: $0 beyond what we already had. No subscription, no proxy fighting Bubble’s infrastructure, nothing that can quietly stop working on someone else’s timeline.

The honest tradeoff

The static snapshots aren’t live. If a treatment’s price or copy changes in Bubble, it won’t reflect in what crawlers see until the next scheduled scrape (ours runs nightly). For a public content site — treatments, blog, gallery, FAQs — that’s a completely acceptable trade for guaranteed crawlability. It would be the wrong call for something like a logged-in dashboard where content is different for every user in real time — but that’s exactly the kind of page that never needed to be crawlable in the first place, and in our case, we simply left it on the Bubble subdomain, untouched.

If you’re hitting this right now

  1. Confirm it first — curl -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" https://yoursite.com/ and look for real visible text in the raw output. Empty shell of <script> tags = you have this problem.
  2. Check your navigation — search the same raw output for <a href. If your main nav doesn’t show up as real links, you likely have Bubble’s Button+workflow issue too, on top of the rendering problem.
  3. If you’re not on a dedicated Bubble plan, go in expecting that Cloudflare-proxy-based fixes (Prerender.io included) will hit the same AAAA/SSL wall we did — it’s not a bug on your end, it’s structural.
  4. Verify any third-party tool’s claims with curl directly, not with Lighthouse or PageSpeed — those only ever show you the JS-rendered version.
  5. The self-built snapshot-plus-Worker pipeline is more setup than a one-click SaaS tool, but it’s free, fully understood, and doesn’t depend on anyone else’s uptime or business model.

Happy to answer questions in the comments if anyone’s mid-fight with this exact problem right now — we know exactly how isolating it feels when your site looks perfect to every human visitor and invisible to everything else. It took us the better part of a week to get from “completely stuck” to “fully working.” If this saves someone else that week, it was worth writing up.

(written with assistance of ai that I implimented the fixes with)

This was the exact issue that caused me to migrate away from bubble to supabase+claude. I lost two months rebuilding but i never have to worry about that problem again. I appreciate the time you took to write about the actual root cause…it’s 100% accurate.

Thank you for sharing this incredible experience!

I am running into the same issue. When we built the site, we never considered SEO or bot traffic. Now the site has been live for over a year with active users, and we are looking to optimize SEO, but here we are facing all the issues you mentioned.

If we were to do the same thing you did, how long would the migration take? We need to make sure our site has as little downtime as possible—ideally just a few hours after midnight.

From a human user’s perspective, Cloudflare directs them to app.domain.com when they land on our site with a standard search or an external/internal link, but does the user see that they are on the subdomain, or can Cloudflare mask that? If Cloudflare can mask the subdomain and show the main domain name, I assume once users sign up or log in, they will just be on app.domain.com since those pages don’t need to be crawled.

All of this is myth not real

I recently did similar but just with bubble + Cloudflare.

All SEO and marketing landing pages are on the main domain and the bubble app now sits on app. domain.

The static html pages, site map and other crawler files are stored in CF KV database. It’s all managed neatly from an admin panel within our bubble app.

The downside is that these static pages are not designed in bubble, they are just html & CSS etc… so we lose out benefits such as dynamic bubble data on the homepage etc

The good part is our lighthouse score got 100! - and the actual user experience has been seemless.

So overall, our team is happy with the result… Just wished bubble provided a native solution for this - I didn’t really ever want to split the site up into two layers.

[quote=“hi126, post:1, topic:398955”]

3\. A Cloudflare Worker sits in front of the root domain and makes one decision per request

[/quote]

[quote=“asked111, post:5, topic:398955”]

All SEO and marketing landing pages are on the main domain and the bubble app now sits on app. domain.

[/quote]

Yep this is the best way to work around this. It’s cheap and it’s pretty easy to set up a workflow that updates your CF store when you update a relevant record.

Another perk is that you can write a version that is AI friendly and get the perks of better GEO on top of SEO.

In theory it is also safer as your human sites are routed after the fact.

what do you mean

So that you can basically have more ‘dynamic’ data in the CF and serve up static pages with up to date data?

I’ve done the same with Cloudflare as well, but I’ve put it on one domain. My Cloudflare edge router takes domain.com and then based on rules routes to either Bubble or other services. In this case, a certain group of bot user-agents are routed to a static version of the site that is saved as HTML via KV and the prerender open source sdk. It works flawless, bots see the static html (which is auto refreshed every 2 days I believe i set it to), and humans see the normal site from Bubble all on the same domain, no subdomains.

Overall it says SEO needs SSR not CSR, it is a myth not real.

Are you saying you have high ranking SEO pages on native Bubble?

Also, I feel like this is actually easy for Bubble to do these days, they should just natively put a cached version of specific pages and refresh them at a certain interval. It’s very similar to the sitemap functionality.

Yes, I have seen 6-8 secs loading pages have good rank, the only thing that is not a myth so far is I heard some featured snippets or else you can’t achieve with low performance

Do they show up in chatGPT? I’ve noticed that chatGPT can’t understand my Bubble site at all, only Gemini (probably because Google has better crawlers). AI crawling would be the biggest reason for SSR.

Come to messages.

How did you test for this? I think mine works…it should lol

Ask chatGPT an extremely specific question about something deep in your page, then ask Gemini the same thing.

I have the opposite problem :sweat_smile:

Hmm strange… I just checked and chatGPT can actually read my Bubble site. They’ve definitely started using a different scraper than a few months ago.

It has always been expressed correctly the onerous of LLMs to access site/app details properly is on LLM and not platform such as Bubble.

LLMs are going to continue development of their own browsers to make it easier for their LLMs to view web pages more fully.

But it is up to site developer to implement their own features and functions for ai agents to perform the actions on behalf of ai agent user, and make those clearly defined to ai agent.

Well some of it is on the Bubble app or really any app owner as well. The LLM bots are gonna respect your robots and ai crawl index files. Also, implementing better standards helps as well. For example, using over a