Ghost Portal / Members (Pro)
Keep Ghost's membership widget active on your static site so subscribers can sign in and pay — while your Ghost backend stays hidden from public search engines.
How it works
Your static site serves all public content from the main domain. Ghost Portal runs as a popup — when a visitor clicks Subscribe or Sign In, the popup authenticates against your Ghost backend on a subdomain. After login, paying members are redirected to the Ghost backend to read gated content.
- Open the Pro Generator and go to the Advanced step.
- Enable the Ghost Portal / Members toggle.
- Generate your site —
portal.min.jsis kept in the static output.
robots.txt to hide it from search engines instead (see below).Example: example.com → static site, ghost.example.com → Ghost backend
- In Ghost Admin → Settings → General, set your site URL to
https://ghost.example.com. - In the SnapStatic wizard: Source Domain =
https://ghost.example.com, Generated Domain =https://example.com. - Enable Ghost Portal in the Advanced step.
- Generate and deploy the static site to
example.com. - In Ghost Admin → Settings → Portal, set the sign-in redirect URL to
https://ghost.example.comso paying members land on the Ghost backend after login to access gated posts.
Static site: https://example.com → all public posts, pages Ghost backend: https://ghost.example.com → member login, paid content, Ghost Admin
Prevent duplicate content by blocking search engines from indexing the Ghost subdomain. Use two layers:
1. robots.txt via Nginx
Add to your Ghost backend's Nginx config, inside the server block:
location = /robots.txt {
add_header Content-Type text/plain;
return 200 "User-agent: *\nDisallow: /\n";
}2. noindex meta tag
In Ghost Admin → Settings → Code Injection → Site Header, add:
<meta name="robots" content="noindex, nofollow">
Both layers together ensure search engines ignore the Ghost subdomain even if robots.txt is bypassed.
Optional. Redirects all public frontend visits from the Ghost subdomain to your static site, while keeping Ghost Admin, member login, and API endpoints accessible. Logged-in members (detected via session cookie) are served directly from Ghost.
Add this to the http block (outside the server block) in your Nginx config:
map $cookie_ghost_members_ssa $is_member {
default 0;
~.+ 1;
}Then in your server block for the Ghost subdomain:
server {
server_name ghost.example.com;
# Ghost Admin, member auth, API, assets — always accessible
location ~ ^/(ghost|members|content)/ {
proxy_pass http://localhost:2368;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# robots.txt — block search engines
location = /robots.txt {
add_header Content-Type text/plain;
return 200 "User-agent: *\nDisallow: /\n";
}
# Frontend — serve for logged-in members, redirect others to static site
location / {
if ($is_member = 0) {
return 302 https://example.com$request_uri;
}
proxy_pass http://localhost:2368;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Replace ghost.example.com and example.com with your actual domains. Reload Nginx after changes: nginx -t && systemctl reload nginx
- Portal buttons visible — visit your static site main domain. Subscribe and Sign In buttons should appear in the theme header/footer.
- Portal popup opens — click Subscribe or Sign In. The Ghost Portal popup should open without errors. Check browser console for no CORS errors.
- Sign-in works — complete a test login. After login the redirect should take you to
ghost.example.com. - Paid content accessible — as a logged-in member, navigate to a member-only post on the Ghost subdomain. Content should be visible.
- SEO check — visit
https://ghost.example.com/robots.txt. Should returnDisallow: /. Visitghost.example.comdirectly — should redirect toexample.com(if Nginx redirect is configured). - Ghost Admin accessible — visit
https://ghost.example.com/ghost/. Should load normally (not redirected).