Installing WP Ghost after Building a Breakdance Site with LiteSpeed Cache and QUIC.cloud CDN Enabled…and how to avoid the AJAX 403 headache – Plot twist at the end…
I built a WordPress site using Breakdance, enabled LiteSpeed Cache, and activated QUIC.cloud CDN, then installed WP Ghost to harden security, – I may found myself suddenly frustrated by persistent 403 errors and being unable to save new content to existing pages – Even though I could create new pages and there be no issue. It was happening on multiple sites…
In particular, this dreaded error:
❌
403 Forbidden
Failed to load resource:/ghost-admin/admin-ajax.php?…
The server responded with a status of 403 ()
This guide explains why it happened, and how to fix it – cleanly (but not quickly – although you wont have to waste 12 hours figuring out what is going or trying to decide between disabling wp-ghost entirely or disabling Quic.Cloud CDN or who to send third party support tickets – this fix will show you how, all with without losing your page data, breaking your custom paths or pulling our your hair – but please skip to the part where you grab a coffee and fix it.
The Stack That “Caused” the Issue
My combo looks like this:
- Breakdance Builder: Used to create site’s layouts
- WP Ghost (Lite Mode): To rewrite and hide common WordPress paths like
/wp-admin/
- LiteSpeed Cache + QUIC.cloud CDN: – For performance and edge-level caching
- DNS pointed to QUIC.cloud (not just the CDN toggled on – Didnt seem to happen using cloudflare DNS with the CDN or if the QUIC.cloud CDN is not enabled)
This setup with the config I was using broke admin-ajax.php requests, which plugins like Breakdance rely on heavily for real-time editing, saving, and builder functionality.
The Core Problem
When WP Ghost is enabled in Lite/Ghost Mode, it rewrites paths like:
/wp-admin/admin-ajax.php → /ghost-admin/admin-ajax.php or
/wp-admin/admin-ajax.php → /ghost-admin/customajax.php
However, Breakdance nonces are bound to the exact AJAX endpoint. If the endpoint path changes, even slightly, the server will reject the request with a 403.

Error Code: 403
Request Time: Sun, 13 Jul 2025 09:55:58 GMT
Request URI: https://mydomain.com.au/ghost-admin/admin-ajax.php?_breakdance_doing_ajax=yes&_ajax_nonce=9a0a1234d0
Request Type: POST
This means (I was thinking…) – Breakdance wont work with custom AJAX endpoints but I was still a little confused as my Ghost Mode (the paid version) Site was working with the custom AJAX end point… I figured maybe it was something to do with how rewrites were applied between the free and paid versions, afterall there were more custom additions to my .htaccess and wp-config in Ghost Mode nonetheless I wanted to be able to provide my clients with easy to update (that breakdance) with fast (thats QuicCloud and the CDN), secure (WP-ghost) websites on (if they choose) budget hosting – so I had to make this work.
My Painstaking Step-by-Step Fix
Here’s the complete fix I tested with Breakdance + WP Ghost Lite installs and it worked – but if you are following these steps to fix the same issue Please for the love of god, skip to the end.
I was getting
WP Ghost Ajax Security Settings
In WP Ghost → Change Paths → Ajax Security I “turned off my custom admin-ajax path
- Deleted my Custom admin-ajax path
Cleared
- Hide wp-admin from Ajax URL:
OFF
- Change Paths in Ajax Calls:
OFF


Unfortunately, it seems rewrites are not compatible with page builders like Breakdance, which rely on strict nonce validation and fixed AJAX paths behind the scenes.
After reverting the setting back to its “default” and turning off the “Hide wp-admin from Ajax URL” option, I thought, “Surely this will fix things.”
But no. Although disabling WP-Ghost entirely fixed it right away.
At this point, I’d just launched the new site for a client. I’d already sent them their custom login link, and they hadn’t logged in yet. It was 9pm, and I was crossing my fingers that they’d gone to bed, giving me a chance to fix everything before morning without compromising their site speed or weakening the security settings I’d worked hard to configure.
At this point, I started wondering – should I just disable the CDN entirely?
I’ve got four other sites running WP Ghost in Lite Mode, using the exact same stack (Breakdance, LiteSpeed Cache, etc.), but they’re not connected to QUIC.cloud CDN yet, they’re still routed through Cloudflare or directly via their domain registrar’s DNS. And guess what? None of them have this issue.
So it’s looking more and more like QUIC.cloud could be the culprit, you see , It operates at the edge (like Cloudflare), processing URLs before your server sees them, so It may apply its own security or caching rules particularly to non-standard paths like /ghost-admin/admin-ajax.php
, maybe that is interfering with nonce validation, AJAX routing, or custom rewrites – all of which Breakdance relies on.
The problem is, changing nameservers isn’t something you can undo quickly. If I were to switch DNS away from QUIC.cloud now, the site might go offline for hours or longer while the change propagates. And if the issue turns out to have nothing to do with the CDN after all? Then I’ve wasted valuable time waiting, potentially broken the site overnight, and still haven’t solved the problem.
So I held off. I didn’t want to make things worse chasing a maybe, and turned to my .htaccess file
Adding Manual Rewrite Exclusions to .htaccess
Breakdance expects AJAX requests to go to:/wp-admin/admin-ajax.php
....and will fail if the path is rewritten to: /ghost-admin/admin-ajax.php
I opened up the .htaccess
file and found the rewrite rule WP Ghost had added – even though I thought I had “turned it off”
RewriteRule ^([0-9a-zA-Z_-]+/)?ghost-admin/(.*) /wp-admin/$2 [QSA,NC,L]
At this point, I wondered if I could just delete the AJAX-related rewrite altogether, and maybe WordPress and Breakdance would ignore the problem or better yet, fix themselves. I removed the AJAX rewrite, but I knew that as soon as I saved the WP Ghost settings again, it would just come back.
Then I thought what if the entire rewrite that Ghost is injecting is still affecting things, even if I’m not actively calling admin-ajax.php
?
Spoiler: I was right.
Even though WP Ghost doesn’t visibly touch admin-ajax.php
, the way it rewrites everything under /wp-admin/
(like the ghost-admin
path) can still interfere with how plugins like Breakdance handle nonces and AJAX calls unless you tell it not to.
So maybe I need to manually update the rewrite rule to exclude admin-ajax.php
from being rewritten at all. Lets try…
# Prevent WP Ghost rewrite from affecting admin-ajax.php
<IfModule mod_rewrite.c>
RewriteEngine On
# Exclude admin-ajax.php from WP Ghost rewrite
RewriteCond %{REQUEST_URI} !admin-ajax\.php$ [NC]
RewriteRule ^([0-9a-zA-Z_-]+/)?ghost-admin/(.*) /wp-admin/$2 [QSA,NC,L]
</IfModule>
Nope still an issue...
Excluding AJAX Calls from LiteSpeed Cache (just in case)
At one point, I started wondering maybe it’s a cache thing after all? Even with the correct rewrite rule and AJAX path, LiteSpeed Cache might still be interfering, especially if it’s trying to cache AJAX responses or defer related scripts.
To rule that out, I turned on Bypass CDN in QuicCloud (desperate to resist the urge to think about updating nameservers) and then in WP Litespeed Cache I updated the following settings:
In WordPress: LiteSpeed Cache
Cache → Excludes → Do Not Cache URIs:/wp-admin/admin-ajax.php
Cache → Excludes → Do Not Cache Query Strings: _breakdance_doing_ajaxand to be extra safe…
Page Optimization → Tuning → JS Excludes:
breakdance-*
…to prevent deferred JS from interfering with builder assets.
I was starting to feel like purging myself, stuck in a cache-clearing Groundhog Day and seriously questioning my life choices.
Purge LiteSpeed Cache → Purge QUIC.cloud CDN cache → Clear your browser cache → Log in → Test in Incognito (again)Maybe it was time to purge myself from the dev game altogether. Surely other designers don’t get this deep in the weeds, right? Why does this always happen to me? I’ve always wondered where exactly does the line between designer and developer get drawn? At what point are you no longer “just” a designer? If you’re deep in
.htaccess
rewrites at 11pm, are you still a designer… or are you in denial about being a dev?If you’re a designer reading this, be honest when would you have thrown in the towel and submitted a support ticket?
And how do you even know which side you’re on? Dev or Design… I still haven’t figured that out.
Back to the Front… or close to the End?
After all the spiralling, I had a thought: What if it’s not Breakdance that’s broken – and its just the old nonce?
If that were the case, then creating a new page should generate a fresh nonce using the correct, updated AJAX path… right?
So I created a brand new page. Hit save. BAM — it worked.
- Breakdance loaded
- Builder saved
- No 403 in sight
It was the first real progress I’d seen in what felt like hours. (And to be clear it was hours. Evening, the next day. I’d technically slept, but still… we were easily somewhere between 5 and … ok closer to 12 hours deep into this mess.)
Honestly, I’m still not sure where I land on the designer vs developer spectrum but if there’s one thing this experience confirmed, it’s that time management is not my strongest attribute. Or maybe I’m just passionately committed to solving things the hard way. Yeah… let’s go with that.
Just Like an Ex: Broken in All the Ways That Matter, Can’t Change Them, and the Best Option Is to Move On, Delete, and Start Again
Breakdance will happily load and save new pages created after the rewrite fix is in place. However, pages created before installing WP Ghost or adjusting the rewrite rules continue to fail with 403 errors.
Why? Because they’re still holding onto a stale builder config one that references an outdated (and now invalid) AJAX path, or a nonce that no longer aligns with the current setup.
But we can save. Thats good news
At this point I was grasping at straws, surely there had to be a way to recover those old pages without manually rebuilding them from scratch?
Thought #1: Just copy and paste into a new page
Nope. Couldn’t even copy a single icon from an old page without triggering the 403 error again. WTF.
Thought #2: Import the page via the Breakdance Design Library
Nope Import Page disabled. (That’s normal sometimes after a site is cloned or migrated, but it still didn’t help.)

Thought #3: Clone the site, create a Design Set, and pull it in as a Full Site page
Sounds smart, right? Nope. When I finally did get the page into the builder…403. Again.
Thought #4: Copy from the front-end using Breakdance’s “Copy Section” JSON feature
This had to work. Surely it would bypass the old nonce system entirely? Right? WRONG.
FARG. FARG. FARK U. FARRRRRRRRRRRRRRRG.
Said in full dev-desperation mode at 1:17am with a half-eaten biscuit and a cold coffee beside me. (that cold coffee would be important shortly)Desperation Debug Move: Delete the Breakdance meta programmatically
Okay, what if it’s just the nonce or builder cache? I ran this snippet to delete all Breakdance builder metadata for an affected page:
$post_id = 20;
delete_post_meta( $post_id, '_breakdance_data' );
delete_post_meta( $post_id, '_breakdance_render_cache' );
delete_post_meta( $post_id, '_breakdance_settings' );
delete_post_meta( $post_id, '_breakdance_version' );I refreshed the page.
Hit save.
It worked.An old page. Saved. Successfully.
I actually spoke out loud “I did it, I f**ING did it!”
I jumped out of my chair and did a little happy dance.Then I sat back down, grinning, and scrolled down the rest of the page.
Farg
Turns out, I had picked the one page that was using a Breakdance template with a full-height (
100vh
) hero section pulled in from the featured image, layered behind the page title.And because I’d cleared the builder data?
It nuked the entire page layout.
Just the outer template sections remained, everything else? Gone.… except the echos of my regret and failure.
Nuclear Option
OK. That’s it. I have it Disable and delete WP Ghost. Disable and delete LiteSpeed Cache. In fact get rid of everything except Breakdance. Then:
- Clone the site
- Then set it as a Design Set
- Re-enable “Copy from Frontend”
- Use that clean JSON-based copy method free from WP-Ghost rewrites and cached nonces
That has to work – While that Clones lets go make a new coffee – that cold one from before, not very appealing.
Cold Coffee & The Real Culprit
I got back to my desk and started flicking between the 50 tabs I had open to retrace where I was up to. And then, almost accidentally, I noticed something.
One of my other WP Ghost-mode sites (the paid version) was open on the Ajax Security page.
And there it was.
Something that made my stomach sink.
Something that made me feel sicker than… well, that cold coffee I never finished.
The custom admin-ajax path is set to: ajax-admin
Do you see it?
No?
Let me write it out one more time, a little bigger perhaps.
The custom admin-ajax path is set to: ajax-admin
now do you see it? I dont even want to say it.
I went back to WP Ghost → Ajax Security
- Custom admin-ajax Path: admin-ajax
- “Hide wp-admin from Ajax URL” is ON
- “Change Paths in Ajax Calls” is OFF
I hit save,
I hit change paths now
I purged again,
I went back to the page.
I made a small change
Clicked Save.
The spinning circle started.
Then it stopped.
The Save button returned, and just like that:
No 403.
Did you catch it?
The real culprit? the one that cost me hours of my life, made me question my entire existence, and triggered an unhealthy number of purge cycles
…was a single file extension.
.php
In the Default Custom admin-ajax Path.
I’m so mad.
I’m so frustrated.
And I’m writing this blog post because maybe it’ll save someone else the hours I’ll never get back.
What I Thought | What Might Actually Be True |
---|---|
WP Ghost rewriting /admin-ajax.php breaks Breakdance | ✅ Still true – (if you add .php to the the new path) for pre-existing content |
Resetting values to default settings would work | ?Not True |
Excluding admin-ajax.php from rewrites fixes it | ✅ Also true as above |
Using a non-.php custom path like /ajax-call works | ✅ True |
I was clever for coming up with the rewrite and the design set and copy would fix | ?Not True |
Right Stack, Wrong Path & Not the Nonce
I had the perfect setup:
- Breakdance
- WP Ghost
- LiteSpeed Cache
- QUIC.cloud CDN
- Clean code
- Solid hosting
- Optimised everything
On paper, it was flawless.
But none of it mattered.
That one detail – just four characters – broke the builder, triggered endless 403 errors, made nonces fail silently, and had me questioning my entire career path.
After all the rewriting, copying, exporting, importing, cloning, purging, debugging, and soul-searching… it came down to this:
Not the Nonce
Not the builder.
Not the browser.
Not the code
Not the cache.
Or the content.
And thank god it was not the CDN. (could you even imagine if I had started there)
It was the path.
That one little .php
extension in the custom admin-ajax
path – the one that looked safe, even defaulted in as if it were the recommended option – and quietly broke everything. Including me. (Maybe just for a second there.)
Breakdance doesn’t care if the path changes – it just needs the nonce and the request to agree.
But slap a .php
on the end, and suddenly everything breaks like it’s 2008 when AJAX was flaky, and every issue got blamed on “a plugin conflict.”
Trusting the Default Was My First Mistake
By default, WP Ghost auto-fills admin-ajax.php
into the Custom AJAX Path field (Im not sure what the value is on initial install).
If you delete what you have in there – it puts the .php right back in as if to say, “Don’t worry, I’ve got you…”
And here’s the thing, for most sites that probably works fine. Even Gutenberg didn’t flinch. Saved pages. No errors.
But Breakdance is built differently. It relies heavily on exact AJAX paths and strict nonce validation to the point where I couldn’t “reset” the nonce without wiping the entire page layout.
? Breakdance devs, if you’re reading this: a way to regenerate a page nonce without nuking the content? That would be nice. Might even fix that Design Library import issue after a migration or clone while you’re at it.‘
One More Rabbit Hole (For You, Not Me)
After thought: I wonder if whitelisting the _breakdance_doing_ajax=yes
query string in WP Ghost might’ve solved the issue with the .php especially if the plugin was intercepting or rewriting AJAX requests that looked suspicious.
I just remembered this from a previous issue I had months back, now I haven’t tested that theory -and as a testament to my renewed commitment to time management and prioritisation… I’m not going to.
But it might have been worth exploring earlier. Or not. I’ll never know.
The Nature of Tech UX Isn’t Just UI
If you’re still here thank you.
Not just for reading, but for being the kind of person who sticks with things long enough to figure them out.
This was meant to be a tutorial.
But it turned into a survival log. A cautionary tale.
A weird little love letter to the part of web development that makes you scream into the void… and then fist-pump at 1:30am when a save button finally works.
You can’t test your plugin for every possible combination of stack, CDN, page builders, and rewrite config. It’s just not realistic. That’s why, when something like this happens, the community depends on real-world users to share what they learned so the next person doesn’t waste half a day wondering if their life choices were the real bug.
I love designing websites, but If I to be a developer then I want to be the kind that knows deep down that there is always a solution, And I won’t rest until I’ve found it, broken it again, tested it sideways, and written a 3,000-word blog post to make sure no one else has to go through it alone.
Thanks for coming along.
And hey if anyone from WP Ghost happens to read this ? I hope you enjoyed my field research. I genuinely love your software, and I plan to implement it across all my client sites, it’s smart, powerful, and solves problems most clients don’t even know they have.
