AnveVoice

Add a Voice AI Agent to a Rails App

Add the AnveVoice voice agent to a Ruby on Rails 7 or 8 app with javascript_include_tag in the application layout, plus CSP and Turbo notes.

How to add AnveVoice to a Ruby on Rails app

Rails renders every page inside app/views/layouts/application.html.erb. Add the AnveVoice script there with javascript_include_tag and a full URL, which the asset pipeline leaves untouched. If you have a Content Security Policy initializer, allow anvevoice.app in script_src. Steps checked against the official documentation on 2026-10-14.

At a glance

  • Where the code goes: app/views/layouts/application.html.erb, inside head or just before </body>
  • Coding needed: One ERB line; a CSP initializer edit only if you enforce a policy
  • Plan limits: None from Rails; works wherever you deploy (Kamal, Heroku, Render, your own server)
  • Time: About 3 minutes

How the layout works

The Rails guide on layouts and rendering explains that the main body of a view is rendered into the unnamed yield of the layout, and that a newly generated app already includes a named yield for the head. Asset helpers such as javascript_include_tag and stylesheet_link_tag are usually placed in the layout's head. The guide also notes these helpers generate links without checking that the asset exists. That behavior is useful here. Pass javascript_include_tag a complete URL instead of a bundled file name, and Rails writes the tag as given. The API documentation for the asset tag helper includes an example with a full address and the async: true option, producing a script element with the async attribute. A bare name such as 'main' would instead be looked up through the asset pipeline and served from /assets, which is the wrong place for a third-party script. The guide is written for Rails 8.1 and the layout structure is the same in recent 7.x releases.

  • 1. Get your install tag — Create the bot in the AnveVoice dashboard at app.anvevoice.app and copy the embed ID. Keep the rest of the URL exactly as written, including the query string. Code: <script src="https://anvevoice.app/embed.js?embedId=YOUR_EMBED_ID" async></script>

Method 1: use javascript_include_tag in the layout

If you prefer plain HTML, paste the literal script tag into the ERB file instead. ERB prints text outside <% %> markers unchanged, so both approaches produce the same page.

  • 1. Open the layout — Edit app/views/layouts/application.html.erb. If you have other layouts (for example admin.html.erb), decide which of them should carry the voice agent.
  • 2. Add the helper before the closing body tag — The async option keeps it from blocking page rendering. Rails renders the attribute as async="async", which is equivalent. Code: <%= javascript_include_tag "https://anvevoice.app/embed.js?embedId=YOUR_EMBED_ID", async: true %> </body> </html>
  • 3. Restart or reload — In development, ERB changes apply on the next request. In production, redeploy; there is no asset precompile step for this tag.

Method 2: add it per page with content_for

The Rails guide describes content_for as the way a view fills a named yield, useful for page-specific script or link elements in an otherwise generic head. To get the voice agent on a few pages only, give the layout a named yield and push the tag from those views.

  • 1. Add a named yield — In the layout, add this before </body>. Code: <%= yield :voice_agent %>
  • 2. Fill it in selected views — In a view such as app/views/pages/pricing.html.erb: Code: <% content_for :voice_agent do %> <%= javascript_include_tag "https://anvevoice.app/embed.js?embedId=YOUR_EMBED_ID", async: true %> <% end %>

Content Security Policy and Turbo

  • CSP: Rails apps can define a policy in config/initializers/content_security_policy.rb. The security guide shows policy.script_src :self, :https, which already allows any HTTPS script host. If yours is stricter, add the origin: policy.script_src :self, "https://anvevoice.app". The guide also describes report-only mode so you can watch violations first.
  • Turbo Drive: Rails 7 and 8 apps use Turbo, which swaps the body on navigation without a full reload. A script tag placed in the layout body is evaluated once and persists, which is the desired behavior; the AnveVoice script also ignores a second copy on the page.
  • Fragment and page caching: if you cache the whole layout (for example with a CDN rule), purge the cache after the first deploy.
  • Environments: wrap the helper in <% if Rails.env.production? %> to keep the button off development and test.

Check that it works

  • 1. Inspect the generated HTML — Open the site in a private window, view source and look for embed.js with the async attribute.
  • 2. Use the button — Click the microphone button, allow access (HTTPS or localhost) and speak or type a question about your site.

Common problems

  • Request goes to /assets/...: the argument was a bare file name. Use the full https address so Rails does not resolve it through the pipeline.
  • Blocked by CSP: the console names script-src. Add the host or switch the policy to report-only while you investigate.
  • Appears twice: the tag exists in both the layout and a content_for block; keep one.
  • Not visible on admin pages: they use another layout file, add the tag there if wanted.

Sources

  • Rails Guides: Layouts and Rendering (asset tags, yield, content_for) (https://guides.rubyonrails.org/layouts_and_rendering.html) — checked 2026-10-14
  • Rails API: ActionView AssetTagHelper (javascript_include_tag, async) (https://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html) — checked 2026-10-14
  • Rails Guides: Securing Rails Applications (Content Security Policy) (https://guides.rubyonrails.org/security.html) — checked 2026-10-14

Related

  • How to add AnveVoice to a Laravel application
  • How to add AnveVoice to a Django project
  • How to add AnveVoice to a Flask application
  • How to add AnveVoice to an Express (Node.js) site

Try AnveVoice on your site

Free plan: $0, 50,000 tokens a month, no card. Get your embed ID in the dashboard, then paste one tag.