All articles Integration

Add Device Fingerprinting to a Ruby on Rails App

Rails makes it easy to trust params, but a bot posts a form just as convincingly as a person. Device intelligence attaches a verifiable visitor ID and bot score to each submission so your controller can tell them apart before it writes a row.

This guide adds Prynt to Rails with a Stimulus controller for identification and a plain controller action for verification. It fits the Hotwire stack most modern Rails apps already run, so there is no new frontend framework to adopt and no build pipeline to fight.

Load the agent in your bundle

You can import the npm package or drop the CDN build into your layout. The CDN route needs no build step.

<%# app/views/layouts/application.html.erb %>
<script src="https://api.pryntid.com/cdn/prynt.umd.js"></script>

Then initialize the agent in a Stimulus controller so any form can use it.

// app/javascript/controllers/prynt_controller.js
import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
  async connect() {
    this.agent = await Prynt.load({
      apiKey: this.data.get('key'),
      endpoint: 'https://api.pryntid.com'
    })
  }
}

Attach the event ID on submit

Call identify() when the form submits and stash the requestId in a hidden field so it reaches your controller.

async attach(event) {
  const result = await this.agent.identify()
  this.element.querySelector('#prynt_id').value = result.requestId
}
<%= form_with url: signups_path, data: { controller: "prynt", action: "submit->prynt#attach" } do |f| %>
  <%= f.email_field :email %>
  <%= f.hidden_field :prynt_id, id: "prynt_id" %>
  <%= f.submit "Sign up" %>
<% end %>

The browser only collects the signal; the controller decides.

Verify in the controller

Look the event up with your secret key from Rails credentials and branch on the result.

# app/controllers/signups_controller.rb
def create
  res = Net::HTTP.get_response(
    URI("https://api.pryntid.com/v1/events/#{params[:prynt_id]}"),
    { "Authorization" => "Bearer #{Rails.application.credentials.prynt_secret}" }
  )
  event = JSON.parse(res.body)
  if event.dig("bot", "result") == "automated"
    return head :forbidden
  end
  # store event["visitorId"] on the user record
end

Persisting visitorId lets you catch one device creating many accounts. The full field list, including proxy and ASN data, is in the server-side verification docs.

For production, move the HTTP call into a small service object or a background-safe wrapper with a timeout, so a slow verification never blocks a request indefinitely. Decide up front how to behave if the Prynt API is briefly unreachable: for a login you might allow the request but flag it for review, while for a payout you might hold it. Storing each event’s visitorId and confidence on the record also gives your team an audit trail to investigate disputes later, rather than a decision that vanishes the moment the request completes.

Guard forms directly

For login or contact forms, let Form Shield watch the element and add behavioral signals for scripted fills.

this.agent.protectForm(this.element, {
  autoGuard: true,
  expectedScripts: ['latin']
})

expectedScripts flags submissions in unexpected writing systems, a reliable spam tell for Latin-script audiences. It works alongside your controller verification, adding a behavioral layer to the identity check.

Branch on the score

Use the score to route rather than hard-block: clean requests pass, borderline ones get an email confirmation or challenge. Because Prynt runs as a managed cloud service, geolocation, VPN detection, and bot scoring arrive with no infrastructure to maintain, and the free tier covers early traffic while you validate the integration.

Add your key to credentials, wire the Stimulus controller, and verify in the action. See the pricing and free plan to start, and your Rails app will reject bots before they reach the database.

Try it free

Prynt is device intelligence with a free tier — visitor IDs, bot & fraud Smart Signals, and behavioral biometrics, powered by a cross-site network. Start free.

Keep reading