MenuRuby on Rails

Installation guides

Ruby on Rails

Add ProductLense to a Rails app in the application layout, then identify the signed-in user with a safely encoded id. Works with Turbo.

In Rails the script goes into the layout every page renders, usually app/views/layouts/application.html.erb. Turbo Drive changes the URL with the history API, which ProductLense records as pageviews, and it keeps the script loaded across visits.

Add the script

Replace SITE_ID with the id from Settings → Sites in the ProductLense dashboard.

app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= content_for(:title) || "Example" %></title>
    <%= csrf_meta_tags %>
    <script>window.productlense=window.productlense||function(){(window.productlense.q=window.productlense.q||[]).push(arguments)}</script>
    <script defer data-site="SITE_ID" src="https://api.productlense.app/a.js"></script>
    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>
  </head>
  <body>
    <%= yield %>
  </body>
</html>

To keep the site id out of the template, store it in credentials and print it with <%= Rails.application.credentials.dig(:productlense, :site_id) %>.

Identify users

to_json escapes <, > and & by default in Rails, so the value is safe inside a script block:

app/views/layouts/application.html.erb
<% if current_user %>
  <script>
    window.productlense('identify', <%= current_user.id.to_s.to_json.html_safe %>, { email: <%= current_user.email.to_json.html_safe %> });
  </script>
<% end %>

Put it in the <body>, so Turbo runs it again after each visit. Repeated identify calls with the same id are harmless. Use the same id you store on the customer in your billing provider; see how payments are attributed.

Content Security Policy

If config/initializers/content_security_policy.rb is enabled, allow ProductLense and give the inline scripts the request nonce:

config/initializers/content_security_policy.rb
Rails.application.configure do
  config.content_security_policy do |policy|
    policy.script_src  :self, "https://api.productlense.app"
    policy.connect_src :self, "https://api.productlense.app"
  end
  config.content_security_policy_nonce_generator = ->(request) { SecureRandom.base64(16) }
  config.content_security_policy_nonce_directives = %w(script-src)
end

Then write the inline scripts as <%= javascript_tag nonce: true do %> ... <% end %>.

Verify your installation

  1. Deploy, then open your site in a normal browser window.
  2. Open the Live page in the ProductLense dashboard. Your visit appears within a few seconds.
  3. In the browser's developer tools, the Network tab shows a POST to https://api.productlense.app/api/e with status 204. Follow a link: Turbo navigates and a second pageview follows.

bin/rails server runs on localhost, where nothing is sent unless you add data-dev="true" to the tag. If the visit does not appear, follow Verify your installation.

    ↑ ↓ to move, Enter to open