Generated banner for Integration Ruby
Generated logo for Integration Ruby

Integration Ruby

PostHogOfficialCreated by PostHog

  • Skill
  • Tool integration
  • Data and AI
  • MIT
  • No issues found

From the author

PostHog integration for any Ruby application using the Ruby SDK
— the description by PostHog

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a structured workflow for integrating PostHog analytics into Ruby applications. It covers the full lifecycle of implementation, from initial setup and event planning to code modification and error tracking. The skill emphasizes best practices such as using environment variables for configuration, implementing instance-based client initialization, and ensuring proper resource cleanup using Ruby's ensure blocks to prevent event loss.

What it does

  • Guides the setup of the posthog-ruby gem within a Ruby project.
  • Provides a step-by-step workflow for planning and implementing event tracking.
  • Demonstrates how to identify users during authentication flows.
  • Includes patterns for capturing exceptions and tracking critical business events.
  • Ensures robust resource management by requiring client shutdown in ensure blocks.
  • Provides reference examples for CLI and script-based Ruby applications.

When to use it

  • When you need to add product analytics to a Ruby-based application.
  • When implementing server-side event tracking for critical business operations.
  • When you need to track user actions or errors in non-web Ruby scripts or CLIs.
  • When you want to follow standardized patterns for PostHog integration in Ruby.

Advantages

  • Promotes consistent event tracking patterns across the codebase.
  • Reduces the risk of data loss by enforcing proper client shutdown procedures.
  • Prevents hardcoding of sensitive API keys through environment variable usage.
  • Provides clear separation between event tracking and core application logic.

Usage examples

“How do I initialize the PostHog client in my Ruby script?”
The agent will provide the PostHog::Client.new initialization pattern, including the use of environment variables for the API key and host, and the requirement to call client.shutdown.
“What is the correct way to track a user action in Ruby?”
The agent will demonstrate the use of the client.capture method, specifying the required distinct_id, event name, and properties hash.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/posthog/integration-ruby/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip integration-ruby.zip -d .agents/skills

Documentation by PostHog

PostHog integration for Ruby

This skill helps you add PostHog analytics to Ruby applications.

Workflow

Follow these steps in order to complete the integration:

  1. basic-integration-1.0-begin.md - PostHog Setup - Begin ← Start here

  2. basic-integration-1.1-edit.md - PostHog Setup - Edit

  3. basic-integration-1.2-revise.md - PostHog Setup - Revise

  4. basic-integration-1.3-conclude.md - PostHog Setup - Conclusion

Reference files

  • references/EXAMPLE.md - Ruby example project code

  • references/ruby.md - Ruby - docs

  • references/identify-users.md - Identify users - docs

  • references/basic-integration-1.0-begin.md - PostHog setup - begin

  • references/basic-integration-1.1-edit.md - PostHog setup - edit

  • references/basic-integration-1.2-revise.md - PostHog setup - revise

  • references/basic-integration-1.3-conclude.md - PostHog setup - conclusion

The example project shows the target implementation pattern. Consult the documentation for API details.

Key principles

  • Environment variables: Always use environment variables for PostHog keys. Never hardcode them.

  • Minimal changes: Add PostHog code alongside existing integrations. Don't replace or restructure existing code.

  • Match the example: Your implementation should follow the example project's patterns as closely as possible.

Framework guidelines

  • posthog-ruby is the Ruby SDK gem name (add gem 'posthog-ruby' to Gemfile) but require it with require 'posthog' (NOT require 'posthog-ruby')

  • Use PostHog::Client.new(api_key: key, host: host) for instance-based initialization in scripts and CLIs

  • In CLIs and scripts: MUST call client.shutdown before exit or all events are lost

  • Use begin/rescue/ensure with shutdown in the ensure block for proper cleanup

  • capture and identify take a single hash argument: client.capture(distinct_id: 'user_123', event: 'my_event', properties: { key: 'value' })

  • capture_exception takes POSITIONAL args (not keyword): client.capture_exception(exception, distinct_id, additional_properties) — do NOT use distinct_id: keyword syntax

Identifying users

Identify users during login and signup events. Refer to the example code and documentation for the correct identify pattern for this framework. If both frontend and backend code exist, pass the client-side session and distinct ID using X-POSTHOG-DISTINCT-ID and X-POSTHOG-SESSION-ID headers to maintain correlation.

Error tracking

Add PostHog error tracking to relevant files, particularly around critical user flows and API boundaries.

Files

references/EXAMPLE.md

PostHog Ruby Example Project

Repository: https://github.com/PostHog/context-mill Path: basics/ruby


README.md

PostHog Ruby Example - CLI Todo App

A simple command-line todo application built with plain Ruby (no frameworks) demonstrating PostHog integration for CLIs, scripts, data pipelines, and non-web Ruby applications.

Purpose

This example serves as:

  • Verification that the context-mill wizard works for plain Ruby projects

  • Reference implementation of PostHog best practices for non-framework Ruby code

  • Working example you can run and modify

Features Demonstrated

  • Instance-based API - Uses PostHog::Client.new(...) for explicit client management

  • Proper shutdown - Uses shutdown in ensure block to flush events before exit

  • Event tracking - Captures user actions with distinct_id and properties

  • User identification - Associates properties with users via identify

  • Error handling - Manual exception capture for handled errors

Quick Start

1. Install Dependencies
# Install bundler if needed
gem install bundler

# Install dependencies
bundle install
2. Configure PostHog
# Copy environment template
cp .env.example .env

# Edit .env and add your PostHog project token
# POSTHOG_PROJECT_TOKEN=phc_your_project_token_here
# POSTHOG_HOST=https://us.i.posthog.com
3. Run the App
# Add a todo
ruby todo.rb add "Buy groceries"

# List all todos
ruby todo.rb list

# Complete a todo
ruby todo.rb complete 1

# Delete a todo
ruby todo.rb delete 1

# Show statistics
ruby todo.rb stats

What Gets Tracked

The app tracks these events in PostHog:

EventPropertiesPurpose
todo_addedtodo_id, todo_length, total_todosWhen user adds a new todo
todos_viewedtotal_todos, completed_todosWhen user lists todos
todo_completedtodo_id, time_to_complete_hoursWhen user completes a todo
todo_deletedtodo_id, was_completedWhen user deletes a todo
stats_viewedtotal_todos, completed_todos, pending_todosWhen user views stats

Code Structure

basics/ruby/
├── todo.rb              # Main CLI application
├── Gemfile              # Ruby dependencies
├── .env.example         # Environment variable template
├── .gitignore           # Git ignore rules
└── README.md            # This file

Key Implementation Patterns

1. Instance-Based Initialization
require 'posthog-ruby'

posthog = PostHog::Client.new(
  api_key: api_key,
  host: 'https://us.i.posthog.com',
  on_error: proc { |status, msg| puts "PostHog error: #{status} - #{msg}" }
)
2. Event Tracking Pattern
# Track events with distinct_id
posthog.capture(
  distinct_id: 'user_123',
  event: 'event_name',
  properties: { key: 'value' }
)
3. Proper Shutdown
begin
  # Your application code
ensure
  # Always call shutdown to flush events and close connections
  posthog&.shutdown
end
4. Identifying Users
# Identify users (optional - adds user properties)
posthog.identify(
  distinct_id: 'user_123',
  properties: { email: '[email protected]', plan: 'pro' }
)

Running Without PostHog

The app works fine without PostHog configured - it simply won't track analytics. You'll see a warning message but the app continues to function normally.

Next Steps

  • Modify todo.rb to experiment with PostHog tracking

  • Add new commands and track their usage

  • Explore feature flags: posthog.is_feature_enabled('flag-name', 'user_id')

  • Check your PostHog dashboard to see tracked events

Learn More


.env.example

# PostHog Configuration
POSTHOG_PROJECT_TOKEN=phc_your_project_token_here
POSTHOG_HOST=https://us.i.posthog.com

# Optional: Enable debug mode to see PostHog requests
# POSTHOG_DEBUG=true

Gemfile

source 'https://rubygems.org'

gem 'posthog-ruby', '~> 3.0'
gem 'dotenv', '~> 3.0'

todo.rb

#!/usr/bin/env ruby
# frozen_string_literal: true

# Simple CLI Todo App with PostHog Analytics
#
# A minimal plain Ruby CLI application demonstrating PostHog integration
# for non-framework Ruby projects (CLIs, scripts, data pipelines, etc.).

require 'json'
require 'securerandom'
require 'time'
require 'dotenv/load'
require 'posthog'

# Data file location
DATA_FILE = File.join(Dir.home, '.todo_app.json')

def initialize_posthog
  # Initialize PostHog with instance-based API.
  # Returns PostHog client or nil if project token not configured.
  project_token = ENV['POSTHOG_PROJECT_TOKEN']

  unless project_token
    puts 'WARNING: PostHog not configured (POSTHOG_PROJECT_TOKEN not set)'
    puts '         App will work but analytics won\'t be tracked'
    return nil
  end

  PostHog::Client.new(
    api_key: project_token,
    host: ENV.fetch('POSTHOG_HOST', 'https://us.i.posthog.com'),
    on_error: proc { |status, msg| puts "PostHog error: #{status} - #{msg}" }
  )
end

def get_user_id
  # Get or create a user ID for this installation.
  # Uses a UUID stored in the data file to represent this user.
  if File.exist?(DATA_FILE)
    data = JSON.parse(File.read(DATA_FILE))
    return data['user_id'] if data['user_id']
  end

  "user_#{SecureRandom.hex(4)}"
end

def load_todos
  # Load todos from disk.
  return { 'user_id' => get_user_id, 'todos' => [] } unless File.exist?(DATA_FILE)

  JSON.parse(File.read(DATA_FILE))
end

def save_todos(data)
  # Save todos to disk.
  File.write(DATA_FILE, JSON.pretty_generate(data))
end

def track_event(posthog, event_name, properties = {})
  # Track an event with PostHog.
  return unless posthog

  posthog.capture(
    distinct_id: get_user_id,
    event: event_name,
    properties: properties
  )
end

def cmd_add(text, posthog)
  # Add a new todo item.
  data = load_todos

  todo = {
    'id' => data['todos'].length + 1,
    'text' => text,
    'completed' => false,
    'created_at' => Time.now.iso8601
  }

  data['todos'] << todo
  save_todos(data)

  puts "Added todo ##{todo['id']}: #{todo['text']}"

  track_event(posthog, 'todo_added', {
    'todo_id' => todo['id'],
    'todo_length' => todo['text'].length,
    'total_todos' => data['todos'].length
  })
end

def cmd_list(posthog)
  # List all todos.
  data = load_todos

  if data['todos'].empty?
    puts "No todos yet! Add one with: ruby todo.rb add 'Your task'"
    return
  end

  puts "\nYour Todos (#{data['todos'].length} total):\n\n"

  data['todos'].each do |todo|
    status = todo['completed'] ? 'X' : ' '
    puts "  [#{status}] ##{todo['id']}: #{todo['text']}"
  end

  puts

  track_event(posthog, 'todos_viewed', {
    'total_todos' => data['todos'].length,
    'completed_todos' => data['todos'].count { |t| t['completed'] }
  })
end

def cmd_complete(id, posthog)
  # Mark a todo as completed.
  data = load_todos

  todo = data['todos'].find { |t| t['id'] == id }

  unless todo
    puts "ERROR: Todo ##{id} not found"
    return
  end

  if todo['completed']
    puts "Todo ##{id} is already completed"
    return
  end

  todo['completed'] = true
  todo['completed_at'] = Time.now.iso8601
  save_todos(data)

  puts "Completed todo ##{todo['id']}: #{todo['text']}"

  time_to_complete = (Time.parse(todo['completed_at']) - Time.parse(todo['created_at'])) / 3600.0

  track_event(posthog, 'todo_completed', {
    'todo_id' => todo['id'],
    'time_to_complete_hours' => time_to_complete
  })
end

def cmd_delete(id, posthog)
  # Delete a todo.
  data = load_todos

  todo = data['todos'].find { |t| t['id'] == id }

  unless todo
    puts "ERROR: Todo ##{id} not found"
    return
  end

  data['todos'].delete(todo)
  save_todos(data)

  puts "Deleted todo ##{id}"

  track_event(posthog, 'todo_deleted', {
    'todo_id' => todo['id'],
    'was_completed' => todo['completed']
  })
end

def cmd_stats(posthog)
  # Show usage statistics.
  data = load_todos

  total = data['todos'].length
  completed = data['todos'].count { |t| t['completed'] }
  pending = total - completed

  puts "\nStats:\n\n"
  puts "  Total todos:     #{total}"
  puts "  Completed:       #{completed}"
  puts "  Pending:         #{pending}"
  puts "  Completion rate: #{total > 0 ? format('%.1f', completed.to_f / total * 100) : '0.0'}%"
  puts

  track_event(posthog, 'stats_viewed', {
    'total_todos' => total,
    'completed_todos' => completed,
    'pending_todos' => pending
  })
end

def print_usage
  puts <<~USAGE
    Simple todo app with PostHog analytics

    Usage:
      ruby todo.rb add "Todo text"    Add a new todo
      ruby todo.rb list               List all todos
      ruby todo.rb complete <id>      Mark todo as completed
      ruby todo.rb delete <id>        Delete a todo
      ruby todo.rb stats              Show statistics
  USAGE
end

# Main entry point
posthog = nil

begin
  posthog = initialize_posthog

  command = ARGV[0]

  unless command
    print_usage
    exit 0
  end

  case command
  when 'add'
    text = ARGV[1]
    unless text
      puts 'ERROR: Please provide todo text'
      puts 'Usage: ruby todo.rb add "Your task"'
      exit 1
    end
    cmd_add(text, posthog)
  when 'list'
    cmd_list(posthog)
  when 'complete'
    id = ARGV[1]&.to_i
    unless id && id > 0
      puts 'ERROR: Please provide a valid todo ID'
      puts 'Usage: ruby todo.rb complete <id>'
      exit 1
    end
    cmd_complete(id, posthog)
  when 'delete'
    id = ARGV[1]&.to_i
    unless id && id > 0
      puts 'ERROR: Please provide a valid todo ID'
      puts 'Usage: ruby todo.rb delete <id>'
      exit 1
    end
    cmd_delete(id, posthog)
  when 'stats'
    cmd_stats(posthog)
  else
    puts "ERROR: Unknown command '#{command}'"
    print_usage
    exit 1
  end
rescue StandardError => e
  puts "ERROR: #{e.message}"

  # Manually capture handled errors
  posthog&.capture(
    distinct_id: get_user_id,
    event: '$exception',
    properties: {
      '$exception_type' => e.class.name,
      '$exception_message' => e.message,
      '$exception_list' => [{
        'type' => e.class.name,
        'value' => e.message,
        'stacktrace' => { 'frames' => (e.backtrace || []).first(10).map { |line| { 'filename' => line } } }
      }]
    }
  )

  exit 1
ensure
  # IMPORTANT: Always shutdown PostHog to flush events
  posthog&.shutdown
end

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs an API key

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
PostHog
Publisher
PostHog (Official)
Source
PostHog/skills · skills/posthog/integration/skills/ruby · commit a5d30e7
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced
Also distributed in
PostHog/skills

AutoGineer is not affiliated with or endorsed by PostHog or PostHog.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download integration-ruby.zip