Docs

Ruby on Rails Integration Guide

Add Heyo live chat to your Rails application. Works with Rails 7, Turbo, and Hotwire.

This guide shows you how to add Heyo to your Ruby on Rails application. Compatible with Rails 7, Turbo, and Hotwire.

Installation

Add to Application Layout

Add the Heyo script to app/views/layouts/application.html.erb:

<!DOCTYPE html>
<html>
  <head>
    <title><%= content_for(:title) || "My App" %></title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>
    
    <%# Add Heyo before closing head tag %>
    <script src="https://heyo.so/embed/script" defer data-project-id="<%= Rails.application.credentials.heyo[:project_id] %>"></script>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

Add to config/credentials.yml.enc (edit with rails credentials:edit):

heyo:
  project_id: YOUR_PROJECT_ID

Or use environment variables in config/initializers/heyo.rb:

Rails.application.config.heyo_project_id = ENV['HEYO_PROJECT_ID']

Then in your layout:

<script src="https://heyo.so/embed/script" defer data-project-id="<%= Rails.application.config.heyo_project_id %>"></script>

Pass User Data

Method 1: User Check in ERB

<script src="https://heyo.so/embed/script" defer data-project-id="<%= Rails.application.config.heyo_project_id %>"></script>

<% if user_signed_in? %>
<script>
window.addEventListener('load', function() {
  if (window.HEYO) {
    window.HEYO.init({
      projectId: '<%= Rails.application.config.heyo_project_id %>',
      user: {
        name: '<%= j current_user.name %>',
        email: '<%= j current_user.email %>',
        id: <%= current_user.id %>
      }
    });
  }
});
</script>
<% end %>

Note: Use j helper (alias for escape_javascript) to safely escape JavaScript strings.

Method 2: JSON Helper

For more complex user data:

<% if user_signed_in? %>
<script>
window.addEventListener('load', function() {
  if (window.HEYO) {
    window.HEYO.init({
      projectId: '<%= Rails.application.config.heyo_project_id %>',
      user: <%= raw({
        name: current_user.name,
        email: current_user.email,
        id: current_user.id,
        created_at: current_user.created_at.iso8601
      }.to_json) %>
    });
  }
});
</script>
<% end %>

Advanced Usage

Create a Helper Method

Add to app/helpers/application_helper.rb:

module ApplicationHelper
  def heyo_widget
    project_id = Rails.application.config.heyo_project_id
    return unless project_id.present?
    
    content_tag(:script, nil,
      src: 'https://heyo.so/embed/script',
      defer: true,
      'data-project-id': project_id
    )
  end
  
  def heyo_user_data
    return unless user_signed_in?
    
    user_data = {
      name: current_user.name,
      email: current_user.email,
      id: current_user.id
    }
    
    javascript_tag do
      <<~JS
        window.addEventListener('load', function() {
          if (window.HEYO) {
            window.HEYO.init({
              projectId: '#{Rails.application.config.heyo_project_id}',
              user: #{user_data.to_json}
            });
          }
        });
      JS
    end
  end
end

Usage in layouts:

<head>
  <%= heyo_widget %>
</head>
<body>
  <%= yield %>
  <%= heyo_user_data %>
</body>

Rails 7 + Turbo Compatibility

Heyo works with Turbo out of the box. The widget persists across Turbo Drive navigations.

If you need to reinitialize on Turbo navigation:

<script>
document.addEventListener('turbo:load', function() {
  if (window.HEYO) {
    window.HEYO.show();
  }
});
</script>

Stimulus Controller Integration

Create app/javascript/controllers/heyo_controller.js:

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  connect() {
    // Controller connected
  }

  open(event) {
    event.preventDefault()
    window.HEYO?.show()
  }

  close(event) {
    event.preventDefault()
    window.HEYO?.hide()
  }

  toggle(event) {
    event.preventDefault()
    window.HEYO?.toggle()
  }
}

Usage in views:

<button data-controller="heyo" data-action="click->heyo#open">
  Need Help?
</button>

ViewComponent Integration

Create app/components/heyo/widget_component.rb:

# frozen_string_literal: true

module Heyo
  class WidgetComponent < ViewComponent::Base
    def initialize(user: nil)
      @user = user
    end

    def project_id
      Rails.application.config.heyo_project_id
    end

    def user_data
      return nil unless @user

      {
        name: @user.name,
        email: @user.email,
        id: @user.id
      }
    end
  end
end

Create app/components/heyo/widget_component.html.erb:

<script src="https://heyo.so/embed/script" defer data-project-id="<%= project_id %>"></script>

<% if user_data %>
<script>
window.addEventListener('load', function() {
  if (window.HEYO) {
    window.HEYO.init({
      projectId: '<%= project_id %>',
      user: <%= raw user_data.to_json %>
    });
  }
});
</script>
<% end %>

Usage:

<%= render Heyo::WidgetComponent.new(user: current_user) %>

Multi-Tenant Applications

For multi-tenant Rails apps:

<%
  project_id = current_tenant.heyo_project_id || Rails.application.config.heyo_project_id
%>

<script src="https://heyo.so/embed/script" defer data-project-id="<%= project_id %>"></script>

Content Security Policy

If using CSP, add to config/initializers/content_security_policy.rb:

Rails.application.config.content_security_policy do |policy|
  policy.script_src :self, :https, 'https://heyo.so'
  policy.connect_src :self, :https, 'wss://heyo.so', 'https://heyo.so'
end

Route-Based Control

Show chat only on specific routes:

<% unless request.path.start_with?('/checkout') %>
  <%= heyo_widget %>
<% end %>

Or using route helpers:

<% unless current_page?(checkout_path) %>
  <%= heyo_widget %>
<% end %>

Best Practices

  • Store Project ID in credentials or environment variables
  • Use j helper to escape JavaScript strings
  • Use to_json for complex data structures
  • Create helpers or components for reusability
  • Check user authentication before passing data
  • Test with Turbo Drive navigation

Troubleshooting

Widget not appearing

  • Verify HEYO_PROJECT_ID is set
  • Check credentials are loaded properly
  • Look for JavaScript errors in console

User data not showing

  • Use j helper for string escaping
  • Ensure user_signed_in? returns true
  • Check JSON encoding is valid

Turbo navigation issues

  • Widget should persist by default
  • Add turbo:load listener if needed
  • Check that script isn't being removed

CSP blocking script

  • Add heyo.so to script-src
  • Add WebSocket connection to connect-src

Next Steps