Install StageWhisper in Ruby on Rails
In Ruby on Rails the StageWhisper loader has one natural home: your application
layout’s <head>. One paste covers every page, the
built-in CSP helpers hand the widget its nonce, and Turbo Drive needs no extra
wiring.
Prerequisites
- A StageWhisper site created in the dashboard.
- Your app’s origin on the site’s origin allowlist — enable the localhost toggle for local testing.
Add the loader to your layout
-
Copy the one-liner below and swap
pub_your_site_keyfor the public site key shown on your site’s install page in the dashboard.Loader snippet <script async src="https://cdn.stagewhisper.co/loader.js" data-sw-key="pub_your_site_key"></script> -
Paste it into your application layout’s
<head>(app/views/layouts/application.html.erb), just before the closing</head>tag:Layout excerpt <!-- app/views/layouts/application.html.erb --> <head> <title>MyApp</title> <%= csp_meta_tag %> <%= stylesheet_link_tag :app, "data-turbo-track": "reload" %> <%= javascript_importmap_tags %> <script async src="https://cdn.stagewhisper.co/loader.js" data-sw-key="pub_your_site_key"></script> </head> -
Deploy. The tag is
async, so it never blocks your page render — every page served through the layout now carries the widget.
Strict CSP: wire the nonce
Keep csp_meta_tag in your layout head — Rails’
default layout already renders it. When your content security policy carries
a nonce, that helper emits it as meta[name="csp-nonce"], and the
loader reads that value as a fallback and carries it through to the widget
bundle. Alternatively, put the nonce attribute on the loader tag itself with
content_security_policy_nonce:
<script async src="https://cdn.stagewhisper.co/loader.js"
data-sw-key="pub_your_site_key"
nonce="<%= content_security_policy_nonce %>"></script>
Your own inline scripts can carry the same policy nonce by rendering them with
javascript_tag nonce: true. For the exact directives to merge
into your policy — and where the nonce goes in each install variant
— see the
Content Security Policy guide.
Turbo Drive
Nothing to do here. The loader lives in <head>, which
Turbo Drive preserves across visits while it swaps the <body>
— so the widget initializes once and stays mounted. No re-initialization,
no turbo:load hooks; the widget re-evaluates your URL rules on
every navigation by itself.
Verify
Refresh your app, then watch the site’s install status in the dashboard — it flips the moment the first ping arrives.
Widget not showing up? Head to Troubleshooting for the usual suspects — blocked origins, CSP, localhost, and stale config.