This guide shows you how to add Heyo to your Ruby on Rails application. Compatible with Rails 7, Turbo, and Hotwire.
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>
<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.
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 %>
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>
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>
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>
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) %>
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>
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
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 %>
j helper to escape JavaScript stringsto_json for complex data structuresj helper for string escapinguser_signed_in? returns true