https://github.com/rameerez/umami-ruby
⚪️ Ruby wrapper for the Umami analytics API
https://github.com/rameerez/umami-ruby
analytics google-analytics ruby ruby-on-rails umami umami-analytics web-analytics web-development
Last synced: 4 months ago
JSON representation
⚪️ Ruby wrapper for the Umami analytics API
- Host: GitHub
- URL: https://github.com/rameerez/umami-ruby
- Owner: rameerez
- License: mit
- Created: 2024-07-22T15:03:23.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-07-25T19:59:13.000Z (almost 2 years ago)
- Last Synced: 2025-07-09T06:52:03.676Z (11 months ago)
- Topics: analytics, google-analytics, ruby, ruby-on-rails, umami, umami-analytics, web-analytics, web-development
- Language: Ruby
- Homepage: https://rameerez.github.io/umami-ruby/
- Size: 116 KB
- Stars: 4
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# 📊 `umami-ruby` – Ruby client for the Umami Analytics API
[](https://badge.fury.io/rb/umami-ruby) [](https://github.com/rameerez/umami-ruby/actions)
> [!TIP]
> **🚀 Ship your next Rails app 10x faster!** I've built **[RailsFast](https://railsfast.com/?ref=umami-ruby)**, a production-ready Rails boilerplate template that comes with everything you need to launch a software business in days, not weeks. Go [check it out](https://railsfast.com/?ref=umami-ruby)!
`umami-ruby` is a comprehensive Ruby wrapper for the [Umami Analytics API](https://umami.is/docs/api). Works with both Umami Cloud and self-hosted instances.
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'umami-ruby'
```
And then execute:
```
$ bundle install
```
Or install it yourself as:
```
$ gem install umami-ruby
```
## Documentation
Full API documentation is available [online](https://rameerez.github.io/umami-ruby/) or can be generated using YARD:
```bash
yard doc
yard server
```
## Configuration
You can put this config in a handy location within your Rails project, like `config/initializers/umami.rb`
### For Umami Cloud
```ruby
Umami.configure do |config|
config.access_token = "your_api_key"
# No need to specify uri_base - automatically uses https://api.umami.is
end
```
### For Self-Hosted Umami Instances
```ruby
# With an access token
Umami.configure do |config|
config.uri_base = "https://your-umami-instance.com"
config.access_token = "your_access_token"
end
# Or with username and password
Umami.configure do |config|
config.uri_base = "https://your-umami-instance.com"
config.credentials = {
username: "your_username",
password: "your_password"
}
end
```
### Configuration Options
| Option | Description | Default |
|--------|-------------|---------|
| `access_token` | API key for Umami Cloud or access token for self-hosted | `nil` |
| `uri_base` | Base URL for self-hosted instances | Auto-detected |
| `credentials` | Hash with `:username` and `:password` for self-hosted | `nil` |
| `request_timeout` | Request timeout in seconds | `120` |
```ruby
# Example with custom timeout
Umami.configure do |config|
config.access_token = "your_api_key"
config.request_timeout = 60 # 60 seconds
end
```
## Usage
### Basic Usage
```ruby
client = Umami::Client.new
# Get current user info
me = client.me
# Get all websites
websites = client.websites
# Get a specific website
website = client.website("website_id")
# Verify token
token_info = client.verify_token
```
### Website Statistics
```ruby
# Get website stats for a time range (timestamps in milliseconds)
stats = client.website_stats("website_id", {
startAt: 1656679719687,
endAt: 1656766119687
})
# Get active visitors (last 5 minutes)
active = client.website_active_visitors("website_id")
# Get pageviews with time grouping
pageviews = client.website_pageviews("website_id", {
startAt: 1656679719687,
endAt: 1656766119687,
unit: "day",
timezone: "America/Los_Angeles"
})
# Get metrics by type
metrics = client.website_metrics("website_id", {
startAt: 1656679719687,
endAt: 1656766119687,
type: "browser" # or: path, referrer, os, device, country, etc.
})
# Get realtime stats (last 30 minutes)
realtime = client.realtime("website_id")
```
### Sending Events
Send custom events to Umami for tracking. This is useful for server-side event tracking.
```ruby
client = Umami::Client.new
# Send a basic event
client.send_event({
website: "your-website-id",
url: "/checkout",
hostname: "example.com",
name: "purchase_completed"
})
# Send an event with custom data
client.send_event({
website: "your-website-id",
url: "/checkout",
hostname: "example.com",
name: "purchase_completed",
language: "en-US",
screen: "1920x1080",
title: "Checkout - Example Store",
data: {
order_id: "12345",
total: 99.99,
currency: "USD"
}
})
# Send with a custom User-Agent (optional)
client.send_event(payload, user_agent: "MyApp/1.0")
```
**Important notes about `send_event`:**
- No authentication token is sent (not required by the API)
- A `User-Agent` header is automatically included (required by Umami)
- For Umami Cloud, requests go to `https://cloud.umami.is/api/send` (different from other API calls)
- For self-hosted, requests go to your configured `uri_base`
### Sessions
```ruby
# Get sessions within a time range
sessions = client.website_sessions("website_id", {
startAt: 1656679719687,
endAt: 1656766119687,
page: 1,
pageSize: 20
})
# Get session statistics
stats = client.website_sessions_stats("website_id", {
startAt: 1656679719687,
endAt: 1656766119687
})
# Get individual session details
session = client.website_session("website_id", "session_id")
# Get session activity
activity = client.website_session_activity("website_id", "session_id", {
startAt: 1656679719687,
endAt: 1656766119687
})
```
### Events Data
```ruby
# Get paginated event list with search
events = client.website_events_list("website_id", {
startAt: 1656679719687,
endAt: 1656766119687,
search: "click",
page: 1,
pageSize: 20
})
# Get event data aggregations
event_data = client.website_event_data_events("website_id", {
startAt: 1656679719687,
endAt: 1656766119687
})
# Get event statistics
stats = client.website_event_data_stats("website_id", {
startAt: 1656679719687,
endAt: 1656766119687
})
```
### Reports
```ruby
# List reports (optionally filter by website and/or type)
all_reports = client.reports
website_reports = client.reports(websiteId: "website_id")
funnel_reports = client.reports(websiteId: "website_id", type: "funnel")
# Create a report
report = client.create_report({
websiteId: "website_id",
type: "funnel",
name: "Checkout Funnel",
parameters: {
startDate: "2024-01-01T00:00:00Z",
endDate: "2024-01-31T23:59:59Z"
}
})
# Run specialized reports
funnel = client.report_funnel({
websiteId: "website_id",
startDate: "2024-01-01T00:00:00Z",
endDate: "2024-01-31T23:59:59Z",
steps: [
{ type: "path", value: "/" },
{ type: "path", value: "/checkout" },
{ type: "path", value: "/thank-you" }
],
window: 7
})
retention = client.report_retention({
websiteId: "website_id",
startDate: "2024-01-01T00:00:00Z",
endDate: "2024-01-31T23:59:59Z",
timezone: "America/Los_Angeles"
})
# Available report types: attribution, breakdown, funnel, goal, journey, retention, revenue, utm
```
**Report types:**
| Type | Description |
|------|-------------|
| `attribution` | Marketing channel attribution analysis |
| `breakdown` | Multi-dimensional data segmentation |
| `funnel` | Conversion funnel tracking |
| `goal` | Goal performance metrics |
| `journey` | User navigation path analysis |
| `retention` | Return visitor analysis |
| `revenue` | Revenue tracking and analysis |
| `utm` | UTM campaign parameter breakdown |
### User & Team Management
```ruby
# Get current user info
me = client.me
my_teams = client.my_teams(page: 1, pageSize: 10)
my_websites = client.my_websites(includeTeams: true)
# Team management
teams = client.teams
team = client.team("team_id")
client.create_team("My Team")
client.add_team_user("team_id", "user_id", "team-member")
# User management (admin only, self-hosted)
users = client.admin_users
client.create_user("username", "password", "user")
```
### Website Management
```ruby
# Create a website
website = client.create_website({
name: "My Website",
domain: "example.com",
teamId: "optional-team-id"
})
# Update a website
client.update_website("website_id", {
name: "Updated Name",
shareId: "public-share-id"
})
# Reset website data
client.reset_website("website_id")
# Delete a website
client.delete_website("website_id")
```
## Available Methods
### Authentication
- `verify_token` - Verify the current authentication token
### Me (Current User)
- `me` - Get current user information
- `my_teams(params)` - Get user's teams (supports pagination)
- `my_websites(params)` - Get user's websites
### Admin (Self-hosted only)
- `admin_users(params)` - List all users
- `admin_websites(params)` - List all websites
- `admin_teams(params)` - List all teams
### Users
- `create_user(username, password, role, id:)` - Create a user
- `user(user_id)` - Get user by ID
- `update_user(user_id, params)` - Update user
- `delete_user(user_id)` - Delete user
- `user_websites(user_id, params)` - Get user's websites
- `user_teams(user_id, params)` - Get user's teams
### Teams
- `teams(params)` - List all teams
- `create_team(name)` - Create a team
- `join_team(access_code)` - Join a team
- `team(team_id)` - Get team by ID
- `update_team(team_id, params)` - Update team
- `delete_team(team_id)` - Delete team
- `team_users(team_id, params)` - List team members
- `add_team_user(team_id, user_id, role)` - Add user to team
- `team_user(team_id, user_id)` - Get team member
- `update_team_user(team_id, user_id, role)` - Update member role
- `delete_team_user(team_id, user_id)` - Remove user from team
- `team_websites(team_id, params)` - List team websites
### Websites
- `websites(params)` - List all websites
- `create_website(params)` - Create a website
- `website(website_id)` - Get website by ID
- `update_website(website_id, params)` - Update website
- `delete_website(website_id)` - Delete website
- `reset_website(website_id)` - Reset website data
### Website Statistics
- `website_stats(website_id, params)` - Get statistics
- `website_active_visitors(website_id)` - Get active visitors
- `website_pageviews(website_id, params)` - Get pageviews
- `website_events(website_id, params)` - Get events (time-series)
- `website_events_series(website_id, params)` - Get events series
- `website_metrics(website_id, params)` - Get metrics
- `website_metrics_expanded(website_id, params)` - Get expanded metrics
### Sessions
- `website_sessions(website_id, params)` - List sessions
- `website_sessions_stats(website_id, params)` - Get session stats
- `website_sessions_weekly(website_id, params)` - Get weekly breakdown
- `website_session(website_id, session_id)` - Get session details
- `website_session_activity(website_id, session_id, params)` - Get activity
- `website_session_properties(website_id, session_id)` - Get properties
- `website_session_data_properties(website_id, params)` - Get data properties
- `website_session_data_values(website_id, params)` - Get data values
### Events
- `website_events_list(website_id, params)` - List events (paginated)
- `website_event_data(website_id, event_id)` - Get event data
- `website_event_data_events(website_id, params)` - Get event aggregations
- `website_event_data_fields(website_id, params)` - Get event fields
- `website_event_data_properties(website_id, params)` - Get event properties
- `website_event_data_values(website_id, params)` - Get event values
- `website_event_data_stats(website_id, params)` - Get event statistics
### Realtime
- `realtime(website_id)` - Get realtime stats (last 30 minutes)
### Links
- `links(params)` - List all links
- `link(link_id)` - Get link by ID
- `update_link(link_id, params)` - Update link
- `delete_link(link_id)` - Delete link
### Pixels
- `pixels(params)` - List all pixels
- `pixel(pixel_id)` - Get pixel by ID
- `update_pixel(pixel_id, params)` - Update pixel
- `delete_pixel(pixel_id)` - Delete pixel
### Reports
- `reports(params)` - List all reports (filter by `websiteId`, `type`)
- `create_report(params)` - Create a report
- `report(report_id)` - Get report by ID
- `update_report(report_id, params)` - Update report
- `delete_report(report_id)` - Delete report
- `report_attribution(params)` - Run attribution report
- `report_breakdown(params)` - Run breakdown report
- `report_funnel(params)` - Run funnel report
- `report_goals(params)` - Run goals report
- `report_journey(params)` - Run journey report
- `report_retention(params)` - Run retention report
- `report_revenue(params)` - Run revenue report
- `report_utm(params)` - Run UTM report
### Sending Events
- `send_event(payload, user_agent:)` - Send tracking event
## Error Handling
The gem defines several custom error classes:
```ruby
begin
client.website("non-existent-id")
rescue Umami::NotFoundError => e
puts "Website not found: #{e.message}"
rescue Umami::ClientError => e
puts "Client error: #{e.message}"
rescue Umami::ServerError => e
puts "Server error: #{e.message}"
rescue Umami::AuthenticationError => e
puts "Authentication failed: #{e.message}"
rescue Umami::ConfigurationError => e
puts "Configuration error: #{e.message}"
rescue Umami::APIError => e
puts "API error: #{e.message}"
end
```
**Error class hierarchy:**
- `Umami::Error` - Base error class
- `Umami::ConfigurationError` - Configuration issues
- `Umami::AuthenticationError` - Authentication failures
- `Umami::APIError` - API request failures
- `Umami::NotFoundError` - Resource not found (404)
- `Umami::ClientError` - Client errors (4xx)
- `Umami::ServerError` - Server errors (5xx)
## Logging
The gem uses a logger that can be configured:
```ruby
# Set log level
Umami.logger.level = Logger::DEBUG
# Use a custom logger
Umami.logger = Rails.logger
```
## Development
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run `bundle exec rake install`.
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/rameerez/umami-ruby. Our code of conduct is: just be nice and make your mom proud of what you do and post online.
## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).