Ruby SDK

Send events from any Ruby app using a project API key. Pure stdlib, no external dependencies. Works with Rails, Sinatra, Sidekiq workers, scheduled jobs, and anything else that runs Ruby 3.0+.

clamp-sh/analytics-rubyMIT

Paste to your agent

Wire Clamp into a Rails app
Adds the clamp-analytics gem, initializes it on boot, and tracks the project's primary conversion event from the relevant controller or job.

Install

Gemfile
gem "clamp-analytics"

Then:

terminal
bundle install

Ruby 3.0+ supported. The gem uses only the standard library (net/http, json, time, uri).

Use an API key that starts with sk_proj_ from Settings → API Keys. Keys are scoped to one project.

Quick start

config/initializers/clamp.rb
require "clamp_analytics"

Clamp::Analytics.init(
  project_id: "proj_xxx",
  api_key: ENV.fetch("CLAMP_API_KEY")
)
anywhere.rb
Clamp::Analytics.track("signup", properties: { plan: "pro", method: "email" })

Clamp::Analytics.track(
  "subscription_started",
  properties: {
    plan: "pro",
    total: Clamp::Analytics::Money.new(29.00, "USD")
  },
  anonymous_id: "aid_xxx"
)

API

Clamp::Analytics.init(project_id:, api_key:, endpoint: nil)

Initializes the SDK. Call once at app boot. State is held at the module level behind a Mutex, safe across threads.

Clamp::Analytics.track(name, properties: , anonymous_id: nil, timestamp: nil)

Sends a server event. Returns true on success.

Raises Clamp::Analytics::HTTPError on non-2xx responses, Clamp::Analytics::NotInitializedError if initwasn't called.

Clamp::Analytics::Money

purchase.rb
Clamp::Analytics.track("purchase", properties: {
  plan: "pro",
  total: Clamp::Analytics::Money.new(29.00, "USD"),
  tax: Clamp::Analytics::Money.new(4.35, "USD")
})

amount is in major units (29.00, not 2900). currency is an ISO 4217 code.

Framework integrations

Rails

config/initializers/clamp.rb
require "clamp_analytics"

Clamp::Analytics.init(
  project_id: Rails.application.credentials.clamp[:project_id],
  api_key: Rails.application.credentials.clamp[:api_key]
)
app/controllers/signups_controller.rb
class SignupsController < ApplicationController
  def create
    user = User.create!(signup_params)

    Clamp::Analytics.track("signup",
      properties: { plan: user.plan, method: "email" },
      anonymous_id: cookies[:clamp_aid]
    )

    redirect_to welcome_path
  end
end

Sinatra

app.rb
require "sinatra"
require "clamp_analytics"

configure do
  Clamp::Analytics.init(
    project_id: ENV.fetch("CLAMP_PROJECT_ID"),
    api_key: ENV.fetch("CLAMP_API_KEY")
  )
end

post "/checkout" do
  session = create_stripe_session(params)
  Clamp::Analytics.track("checkout_started",
    properties: { plan: params[:plan] },
    anonymous_id: params[:anon_id]
  )
  json url: session.url
end

Sidekiq

For high-throughput webhook handlers, push the track call to a Sidekiq job so the request returns fast.

app/jobs/report_subscription_started.rb
class ReportSubscriptionStarted
  include Sidekiq::Job

  def perform(plan, amount, currency, anonymous_id)
    Clamp::Analytics.track("subscription_started",
      properties: {
        plan: plan,
        total: Clamp::Analytics::Money.new(amount, currency)
      },
      anonymous_id: anonymous_id
    )
  end
end

Capturing exceptions

Wrap unexpected exceptions and send them as $error events on the same pipeline as the rest of your tracking, queryable via the MCP errors.* tools.

webhook_controller.rb
begin
  process_webhook(payload)
rescue => e
  Clamp::Analytics.capture_error(e, context: { webhook: "stripe", event: payload.type })
  raise
end

See Error capture for the wire shape, length caps, and the MCP read tools.

Errors and retries

The gem is synchronous and raises on failure. There are no automatic retries. Rescue around calls if you want fire-and-forget:

safe_track.rb
begin
  Clamp::Analytics.track("subscription_started", properties: ...)
rescue Clamp::Analytics::Error => e
  Rails.logger.error("clamp: #{e.message}")
end

Linking browser and server events

Pass the anonymous ID from the browser to your API, then include it in server-side calls. See the linking pattern on the server-side docs page; the same pattern applies in Ruby.