Ruby SDK
Official Klime SDK for Ruby. Track events, identify users, and associate them with groups.
Installation
Add this line to your application's Gemfile:
gem 'klime'And then execute:
bundle installOr install it yourself as:
gem install klimeQuick Start
require 'klime'
client = Klime::Client.new(
write_key: 'your-write-key'
)
# Identify a user
client.identify('user_123', {
email: 'user@example.com',
name: 'Stefan'
})
# Track an event
client.track('Button Clicked', {
button_name: 'Sign up',
plan: 'pro'
}, user_id: 'user_123')
# Associate user with a group and set group traits
client.group('org_456', {
name: 'Acme Inc',
plan: 'enterprise'
}, user_id: 'user_123')
# Or just link the user to a group (if traits are already set)
client.group('org_456', user_id: 'user_123')
# Shutdown gracefully
client.shutdownInstallation Prompt
Copy and paste this prompt into Cursor, Copilot, or your favorite AI editor to integrate Klime:
Integrate Klime for customer analytics. Klime tracks user activity to identify which customers are healthy vs at risk of churning.
ANALYTICS MODES (determine which applies):
- Companies & Teams: Your customers are companies with multiple team members (SaaS, enterprise tools)
→ Use identify() + group() + track()
- Individual Customers: Your customers are individuals with private accounts (consumer apps, creator tools)
→ Use identify() + track() only (no group() needed)
KEY CONCEPTS:
- Every track() call requires either user_id OR group_id (no anonymous events)
- Use group_id alone for org-level events (webhooks, cron jobs, system metrics)
- group() links a user to a company AND sets company traits (only for Companies & Teams mode)
- Order doesn't matter - events before identify/group still get attributed correctly
BEST PRACTICES:
- Initialize client ONCE at app startup (initializer or singleton)
- Store write key in KLIME_WRITE_KEY environment variable
- Call shutdown on process exit to flush remaining events (auto-registered via at_exit)
Add to Gemfile: gem 'klime'
Then run: bundle install
Or install directly: gem install klime
require 'klime'
client = Klime::Client.new(write_key: ENV['KLIME_WRITE_KEY'])
# Identify users at signup/login:
client.identify('usr_abc123', { email: 'jane@acme.com', name: 'Jane Smith' })
# Track key activities:
client.track('Report Generated', { report_type: 'revenue' }, user_id: 'usr_abc123')
client.track('Feature Used', { feature: 'export', format: 'csv' }, user_id: 'usr_abc123')
client.track('Teammate Invited', { role: 'member' }, user_id: 'usr_abc123')
# If Companies & Teams mode: link user to their company and set company traits
client.group('org_456', { name: 'Acme Inc', plan: 'enterprise' }, user_id: 'usr_abc123')
INTEGRATION WORKFLOW:
Phase 1: Discover
Explore the codebase to understand:
1. What framework is used? (Rails, Sinatra, Hanami, Rack, etc.)
2. Where is user identity available? (e.g., current_user.id, @current_user.id, session[:user_id], warden.user)
3. Is this Companies & Teams or Individual Customers?
- Look for: organization, workspace, tenant, team, account models → Companies & Teams (use group())
- No company/org concept, just individual users → Individual Customers (skip group())
4. Where do core user actions happen? (controllers, service objects, jobs, callbacks)
5. Is there existing analytics? (search: segment, posthog, mixpanel, amplitude, track)
Match your integration style to the framework's conventions.
Phase 2: Instrument
Add these calls using idiomatic patterns for the framework:
- Initialize client once (Rails: config/initializers/klime.rb, Sinatra: before app.run, Rack: middleware)
- identify() in auth/login success handler
- group() when user-org association is established (Companies & Teams mode only)
- track() for key user actions (see below)
WHAT TO TRACK:
Active engagement (primary): feature usage, resource creation, collaboration, completing flows
Session signals (secondary): login/session start, dashboard access - distinguishes "low usage" from "churned"
Do NOT track: every request, health checks, before_action filters, background jobs
Phase 3: Verify
Confirm: client initialized, shutdown handled, identify/group/track calls added
Phase 4: Summarize
Report what you added:
- Files modified and what was added to each
- Events being tracked (list event names and what triggers them)
- How user_id is obtained (and group_id if Companies & Teams mode)
- Any assumptions made or questionsAPI Reference
Constructor
Klime::Client.new(
write_key:, # Required: Your Klime write key
endpoint: nil, # Optional: API endpoint (default: https://i.klime.com)
flush_interval: nil, # Optional: Milliseconds between flushes (default: 2000)
max_batch_size: nil, # Optional: Max events per batch (default: 20, max: 100)
max_queue_size: nil, # Optional: Max queued events (default: 1000)
retry_max_attempts: nil, # Optional: Max retry attempts (default: 5)
retry_initial_delay: nil, # Optional: Initial retry delay in ms (default: 1000)
flush_on_shutdown: nil, # Optional: Auto-flush on exit (default: true)
on_error: nil, # Optional: Callback for batch failures
on_success: nil # Optional: Callback for successful sends
)Methods
track(event_name, properties = nil, user_id: nil, group_id: nil)
Track an event. Events can be attributed in two ways:
- User events: Provide
user_idto track user activity (most common) - Group events: Provide
group_idwithoutuser_idfor organization-level events
# User event (most common)
client.track('Button Clicked', {
button_name: 'Sign up',
plan: 'pro'
}, user_id: 'user_123')
# Group event (for webhooks, cron jobs, system events)
client.track('Events Received', {
count: 100,
source: 'webhook'
}, group_id: 'org_456')Note: The
group_idparameter can also be combined withuser_idfor multi-tenant scenarios where you need to specify which organization context a user event occurred in.
identify(user_id, traits = nil)
Identify a user with traits.
client.identify('user_123', {
email: 'user@example.com',
name: 'Stefan'
})group(group_id, traits = nil, user_id: nil)
Associate a user with a group and/or set group traits.
# Associate user with a group and set group traits (most common)
client.group('org_456', {
name: 'Acme Inc',
plan: 'enterprise'
}, user_id: 'user_123')
# Just link a user to a group (traits already set or not needed)
client.group('org_456', user_id: 'user_123')
# Just update group traits (e.g., from a webhook or background job)
client.group('org_456', {
plan: 'enterprise',
employee_count: 50
})flush
Manually flush queued events immediately.
client.flushshutdown
Gracefully shutdown the client, flushing remaining events.
client.shutdownFeatures
- Automatic Batching: Events are automatically batched and sent every 2 seconds or when the batch size reaches 20 events
- Automatic Retries: Failed requests are automatically retried with exponential backoff
- Thread-Safe: Safe to use from multiple threads
- Fork-Safe: Automatically detects Puma/Unicorn forks and restarts the worker thread
- Process Exit Handling: Automatically flushes events on process exit (via
at_exit) - Zero Dependencies: Uses only Ruby standard library
Performance
When you call track(), identify(), or group(), the SDK:
- Adds the event to an in-memory queue (microseconds)
- Returns immediately without waiting for network I/O
Events are sent to Klime's servers in a background thread. This means:
- No network blocking: HTTP requests happen asynchronously in a background thread
- No latency impact: Tracking calls add < 1ms to your request handling time
- Automatic batching: Events are queued and sent in batches (default: every 2 seconds or 20 events)
# This returns immediately - no HTTP request is made here
client.track('Button Clicked', { button: 'signup' }, user_id: 'user_123')
# Your code continues without waiting
render json: { success: true }The only blocking operation is flush(), which waits for all queued events to be sent. This is typically only called during graceful shutdown.
Configuration
Default Values
flush_interval: 2000msmax_batch_size: 20 eventsmax_queue_size: 1000 eventsretry_max_attempts: 5 attemptsretry_initial_delay: 1000msflush_on_shutdown: true
Logging
Klime.configure do |config|
config.logger = Rails.logger
endCallbacks
Klime.configure do |config|
config.on_error = Proc.new { |error, batch|
Sentry.capture_exception(error)
}
config.on_success = Proc.new { |response|
Rails.logger.info "Sent #{response.accepted} events"
}
endError Handling
The SDK automatically handles:
- Transient errors (429, 503, network failures): Retries with exponential backoff
- Permanent errors (400, 401): Logs error and drops event
- Rate limiting: Respects
Retry-Afterheader
For synchronous operations, use bang methods (track!, identify!, group!) which raise Klime::SendError on failure.