umami-ruby 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.env.test +9 -0
- data/.simplecov +36 -0
- data/CHANGELOG.md +83 -1
- data/CLAUDE.md +45 -0
- data/README.md +397 -26
- data/Rakefile +10 -1
- data/docs/Umami/APIError.html +2 -2
- data/docs/Umami/AuthenticationError.html +2 -2
- data/docs/Umami/Client.html +11047 -1855
- data/docs/Umami/ClientError.html +2 -2
- data/docs/Umami/Configuration.html +401 -81
- data/docs/Umami/ConfigurationError.html +2 -2
- data/docs/Umami/Error.html +2 -2
- data/docs/Umami/NotFoundError.html +2 -2
- data/docs/Umami/ServerError.html +2 -2
- data/docs/Umami.html +3 -3
- data/docs/_index.html +2 -2
- data/docs/file.CHANGELOG.html +117 -3
- data/docs/file.LICENSE.html +2 -2
- data/docs/file.README.html +465 -30
- data/docs/index.html +465 -30
- data/docs/method_list.html +395 -19
- data/docs/top-level-namespace.html +2 -2
- data/lib/umami/client.rb +989 -192
- data/lib/umami/configuration.rb +62 -0
- data/lib/umami/version.rb +1 -1
- data/lib/umami-ruby.rb +1 -0
- metadata +7 -62
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8123faece9209e2ead6415c0e396a32853aa69ade5a11af2481c311a6e333e81
|
|
4
|
+
data.tar.gz: ad58c5c87d2e27e92e90b7210a7443e589e4879ab9f9f247648b8c43f6af4a99
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5cf0256f92097a0b2374205d727f1deb7f20d3dce31ade6783001023cd7512e76b3b4f65c41dc33166a340d4ae2e1dab60fef3f2043860fec9e3a98c1d1c7d3b
|
|
7
|
+
data.tar.gz: 6f9905fc18ac2200c003d620d5f0f2caac972436b43c9b2756fee76547b7a92ced1358662d5a25300c1d41c3a42a2e847c4bca58d5eed727d57fc90eca1de236
|
data/.env.test
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Test environment configuration (safe to commit)
|
|
2
|
+
# Real credentials should go in .env.test.local (gitignored)
|
|
3
|
+
|
|
4
|
+
UMAMI_ACCESS_TOKEN=test_token_placeholder
|
|
5
|
+
UMAMI_URI_BASE=https://api.umami.is
|
|
6
|
+
|
|
7
|
+
# Test website IDs (using placeholder UUIDs)
|
|
8
|
+
UMAMI_TEST_WEBSITE_ID=00000000-0000-0000-0000-000000000001
|
|
9
|
+
UMAMI_TEST_WEBSITE_ID_ALT=00000000-0000-0000-0000-000000000002
|
data/.simplecov
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SimpleCov configuration file (auto-loaded before test suite)
|
|
4
|
+
# This keeps test_helper.rb clean and follows best practices
|
|
5
|
+
|
|
6
|
+
SimpleCov.start do
|
|
7
|
+
# Use SimpleFormatter for terminal-only output (no HTML generation)
|
|
8
|
+
formatter SimpleCov::Formatter::SimpleFormatter
|
|
9
|
+
|
|
10
|
+
# Track coverage for the lib directory (gem source code)
|
|
11
|
+
add_filter "/test/"
|
|
12
|
+
|
|
13
|
+
# Track Ruby files in lib directory
|
|
14
|
+
track_files "lib/**/*.rb"
|
|
15
|
+
|
|
16
|
+
# Enable branch coverage for more detailed metrics
|
|
17
|
+
enable_coverage :branch
|
|
18
|
+
|
|
19
|
+
# Set minimum coverage threshold to prevent coverage regression
|
|
20
|
+
# Current coverage: Line ~73%, Branch ~73%
|
|
21
|
+
minimum_coverage line: 70, branch: 65
|
|
22
|
+
|
|
23
|
+
# Disambiguate parallel test runs
|
|
24
|
+
command_name "Job #{ENV['TEST_ENV_NUMBER']}" if ENV['TEST_ENV_NUMBER']
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Print coverage summary to terminal after tests complete
|
|
28
|
+
SimpleCov.at_exit do
|
|
29
|
+
SimpleCov.result.format!
|
|
30
|
+
puts "\n" + "=" * 60
|
|
31
|
+
puts "COVERAGE SUMMARY"
|
|
32
|
+
puts "=" * 60
|
|
33
|
+
puts "Line Coverage: #{SimpleCov.result.covered_percent.round(2)}%"
|
|
34
|
+
puts "Branch Coverage: #{SimpleCov.result.coverage_statistics[:branch]&.percent&.round(2) || 'N/A'}%"
|
|
35
|
+
puts "=" * 60
|
|
36
|
+
end
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,86 @@
|
|
|
1
|
-
## [
|
|
1
|
+
## [0.2.0] - 2026-02-02
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
|
|
5
|
+
**New Endpoint Categories:**
|
|
6
|
+
- **Me endpoints**: `me`, `my_teams`, `my_websites` - Get current user info and resources
|
|
7
|
+
- **Admin endpoints**: `admin_users`, `admin_websites`, `admin_teams` - Admin-only endpoints for self-hosted
|
|
8
|
+
- **Sessions endpoints** (8 new methods):
|
|
9
|
+
- `website_sessions` - Get sessions within a time range
|
|
10
|
+
- `website_sessions_stats` - Get summarized session statistics
|
|
11
|
+
- `website_sessions_weekly` - Get session counts by hour of weekday
|
|
12
|
+
- `website_session` - Get individual session details
|
|
13
|
+
- `website_session_activity` - Get session activity
|
|
14
|
+
- `website_session_properties` - Get session properties
|
|
15
|
+
- `website_session_data_properties` - Get session data property counts
|
|
16
|
+
- `website_session_data_values` - Get session data value counts
|
|
17
|
+
- **Realtime endpoint**: `realtime` - Get live stats for last 30 minutes
|
|
18
|
+
- **Links endpoints**: `links`, `link`, `update_link`, `delete_link`
|
|
19
|
+
- **Pixels endpoints**: `pixels`, `pixel`, `update_pixel`, `delete_pixel`
|
|
20
|
+
- **Reports endpoints** (13 new methods):
|
|
21
|
+
- CRUD: `reports`, `create_report`, `report`, `update_report`, `delete_report`
|
|
22
|
+
- Specialized: `report_attribution`, `report_breakdown`, `report_funnel`, `report_goals`, `report_journey`, `report_retention`, `report_revenue`, `report_utm`
|
|
23
|
+
- **Website stats endpoints**:
|
|
24
|
+
- `website_events_series` - Get events series with time bucketing
|
|
25
|
+
- `website_metrics_expanded` - Get detailed metrics with engagement data
|
|
26
|
+
- **Events endpoints**:
|
|
27
|
+
- `website_events_list` - Get paginated event details
|
|
28
|
+
- `website_event_data` - Get data for individual event
|
|
29
|
+
- `website_event_data_events` - Get event data names and counts
|
|
30
|
+
- `website_event_data_fields` - Get event data fields
|
|
31
|
+
- `website_event_data_properties` - Get event properties
|
|
32
|
+
- `website_event_data_values` - Get event data values
|
|
33
|
+
- `website_event_data_stats` - Get aggregated event stats
|
|
34
|
+
|
|
35
|
+
**Configuration:**
|
|
36
|
+
- `request_timeout=` setter - users can now customize timeout via `Umami.configure` block
|
|
37
|
+
- New `UMAMI_CLOUD_SEND_URL` constant for the Cloud send endpoint URL
|
|
38
|
+
- Optional `user_agent:` parameter to `send_event` method for custom User-Agent strings
|
|
39
|
+
|
|
40
|
+
**Documentation:**
|
|
41
|
+
- Configuration Options table in README with all available options and defaults
|
|
42
|
+
- Report Types reference table in README
|
|
43
|
+
|
|
44
|
+
**Test Suite:**
|
|
45
|
+
- Comprehensive Minitest test suite with 152 tests
|
|
46
|
+
- VCR cassettes for all read API endpoints (33 cassettes)
|
|
47
|
+
- CI workflow for Ruby 3.3, 3.4, 4.0
|
|
48
|
+
- ~72% line and branch coverage
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- Updated `website_metrics` documentation with all current metric types
|
|
53
|
+
- Updated user role documentation to include `view-only` option
|
|
54
|
+
- Updated team role documentation with `team-manager`, `team-member`, `team-view-only` roles
|
|
55
|
+
- Updated `send_event` documentation with `tag` and `id` parameters
|
|
56
|
+
- Improved filter parameter documentation across all endpoints
|
|
57
|
+
- Added optional `id` parameter to `create_user` for UUID control
|
|
58
|
+
- Report endpoints use `startDate`/`endDate` (ISO 8601) instead of `startAt`/`endAt` (timestamps)
|
|
59
|
+
- Added `window` parameter to `report_funnel` for days between steps
|
|
60
|
+
- Added `timezone` parameter (required) to `report_retention`
|
|
61
|
+
- Updated `unit` parameter to include `minute` option
|
|
62
|
+
- Made `timezone` required for `website_sessions_weekly`
|
|
63
|
+
- Made `startAt`/`endAt` required for `website_session_activity`
|
|
64
|
+
|
|
65
|
+
### Fixed
|
|
66
|
+
|
|
67
|
+
- **Critical**: Fixed `send_event` to use correct Umami Cloud URL (`https://cloud.umami.is/api/send`)
|
|
68
|
+
- **Critical**: Added mandatory `User-Agent` header to `send_event` requests (fixes [#2](https://github.com/rameerez/umami-ruby/issues/2))
|
|
69
|
+
- Fixed `send_event` to not send unnecessary `Authorization` header
|
|
70
|
+
- Fixed event data endpoint paths from `/api/event-data/...` to `/api/websites/:websiteId/event-data/...`
|
|
71
|
+
- Fixed `verify_token` to use POST method instead of GET
|
|
72
|
+
- Fixed `website_event_data_stats` return type documentation
|
|
73
|
+
|
|
74
|
+
### Deprecated
|
|
75
|
+
|
|
76
|
+
- `event_data_events` - Use `website_event_data_events` instead
|
|
77
|
+
- `event_data_fields` - Use `website_event_data_fields` instead
|
|
78
|
+
- `event_data_stats` - Use `website_event_data_stats` instead
|
|
79
|
+
- `users` - Use `admin_users` instead
|
|
80
|
+
|
|
81
|
+
## [0.1.3] - 2025-02-19
|
|
82
|
+
|
|
83
|
+
- Bug fixes and improvements
|
|
2
84
|
|
|
3
85
|
## [0.1.0] - 2024-07-22
|
|
4
86
|
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
`umami-ruby` is a Ruby wrapper for the Umami Analytics API. It works with both Umami Cloud and self-hosted instances.
|
|
8
|
+
|
|
9
|
+
## Key Files
|
|
10
|
+
|
|
11
|
+
- `lib/umami/client.rb` - Main API client with all endpoint methods
|
|
12
|
+
- `lib/umami/configuration.rb` - Configuration management
|
|
13
|
+
- `lib/umami/errors.rb` - Custom error classes
|
|
14
|
+
- `test/` - Minitest test suite with VCR cassettes
|
|
15
|
+
|
|
16
|
+
## Development Commands
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Install dependencies
|
|
20
|
+
bundle install
|
|
21
|
+
|
|
22
|
+
# Run tests
|
|
23
|
+
bundle exec rake test
|
|
24
|
+
|
|
25
|
+
# Run tests with coverage
|
|
26
|
+
bundle exec rake test # SimpleCov runs automatically
|
|
27
|
+
|
|
28
|
+
# Generate documentation
|
|
29
|
+
yard doc
|
|
30
|
+
yard server
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Testing Guidelines
|
|
34
|
+
|
|
35
|
+
- All tests use VCR cassettes for HTTP interactions
|
|
36
|
+
- Cassettes are in `test/cassettes/`
|
|
37
|
+
- Use `VCR_RECORD_MODE=new_episodes bundle exec rake test` to record new cassettes
|
|
38
|
+
- Anonymize all sensitive data in cassettes before committing
|
|
39
|
+
|
|
40
|
+
## Code Style
|
|
41
|
+
|
|
42
|
+
- Follow standard Ruby conventions
|
|
43
|
+
- Use YARD documentation for all public methods
|
|
44
|
+
- Keep methods focused and single-purpose
|
|
45
|
+
- Error handling uses custom error classes inheriting from `Umami::Error`
|
data/README.md
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
# Umami
|
|
1
|
+
# 📊 `umami-ruby` – Ruby client for the Umami Analytics API
|
|
2
2
|
|
|
3
|
-
[](https://badge.fury.io/rb/umami-ruby)
|
|
3
|
+
[](https://badge.fury.io/rb/umami-ruby) [](https://github.com/rameerez/umami-ruby/actions)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> [!TIP]
|
|
6
|
+
> **🚀 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)!
|
|
7
|
+
|
|
8
|
+
`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.
|
|
6
9
|
|
|
7
10
|
## Installation
|
|
8
11
|
|
|
9
12
|
Add this line to your application's Gemfile:
|
|
10
13
|
|
|
11
14
|
```ruby
|
|
12
|
-
gem 'umami-ruby'
|
|
15
|
+
gem 'umami-ruby'
|
|
13
16
|
```
|
|
14
17
|
|
|
15
18
|
And then execute:
|
|
@@ -33,79 +36,447 @@ yard doc
|
|
|
33
36
|
yard server
|
|
34
37
|
```
|
|
35
38
|
|
|
36
|
-
##
|
|
37
|
-
|
|
38
|
-
### Configuration
|
|
39
|
+
## Configuration
|
|
39
40
|
|
|
40
41
|
You can put this config in a handy location within your Rails project, like `config/initializers/umami.rb`
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
### For Umami Cloud
|
|
43
44
|
|
|
44
45
|
```ruby
|
|
45
|
-
# With username and password
|
|
46
46
|
Umami.configure do |config|
|
|
47
|
-
config.
|
|
48
|
-
|
|
49
|
-
username: "your_username",
|
|
50
|
-
password: "your_password"
|
|
51
|
-
}
|
|
47
|
+
config.access_token = "your_api_key"
|
|
48
|
+
# No need to specify uri_base - automatically uses https://api.umami.is
|
|
52
49
|
end
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### For Self-Hosted Umami Instances
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
```ruby
|
|
55
|
+
# With an access token
|
|
55
56
|
Umami.configure do |config|
|
|
56
57
|
config.uri_base = "https://your-umami-instance.com"
|
|
57
58
|
config.access_token = "your_access_token"
|
|
58
59
|
end
|
|
60
|
+
|
|
61
|
+
# Or with username and password
|
|
62
|
+
Umami.configure do |config|
|
|
63
|
+
config.uri_base = "https://your-umami-instance.com"
|
|
64
|
+
config.credentials = {
|
|
65
|
+
username: "your_username",
|
|
66
|
+
password: "your_password"
|
|
67
|
+
}
|
|
68
|
+
end
|
|
59
69
|
```
|
|
60
70
|
|
|
61
|
-
|
|
71
|
+
### Configuration Options
|
|
72
|
+
|
|
73
|
+
| Option | Description | Default |
|
|
74
|
+
|--------|-------------|---------|
|
|
75
|
+
| `access_token` | API key for Umami Cloud or access token for self-hosted | `nil` |
|
|
76
|
+
| `uri_base` | Base URL for self-hosted instances | Auto-detected |
|
|
77
|
+
| `credentials` | Hash with `:username` and `:password` for self-hosted | `nil` |
|
|
78
|
+
| `request_timeout` | Request timeout in seconds | `120` |
|
|
62
79
|
|
|
63
80
|
```ruby
|
|
81
|
+
# Example with custom timeout
|
|
64
82
|
Umami.configure do |config|
|
|
65
83
|
config.access_token = "your_api_key"
|
|
66
|
-
|
|
84
|
+
config.request_timeout = 60 # 60 seconds
|
|
67
85
|
end
|
|
68
86
|
```
|
|
69
87
|
|
|
70
|
-
|
|
88
|
+
## Usage
|
|
71
89
|
|
|
72
|
-
|
|
90
|
+
### Basic Usage
|
|
73
91
|
|
|
74
92
|
```ruby
|
|
75
93
|
client = Umami::Client.new
|
|
76
94
|
|
|
95
|
+
# Get current user info
|
|
96
|
+
me = client.me
|
|
97
|
+
|
|
77
98
|
# Get all websites
|
|
78
99
|
websites = client.websites
|
|
79
100
|
|
|
80
101
|
# Get a specific website
|
|
81
102
|
website = client.website("website_id")
|
|
82
103
|
|
|
83
|
-
# Get website stats
|
|
84
|
-
stats = client.website_stats("website_id", { startAt: 1656679719687, endAt: 1656766119687 })
|
|
85
|
-
|
|
86
104
|
# Verify token
|
|
87
105
|
token_info = client.verify_token
|
|
88
106
|
```
|
|
89
107
|
|
|
108
|
+
### Website Statistics
|
|
109
|
+
|
|
110
|
+
```ruby
|
|
111
|
+
# Get website stats for a time range (timestamps in milliseconds)
|
|
112
|
+
stats = client.website_stats("website_id", {
|
|
113
|
+
startAt: 1656679719687,
|
|
114
|
+
endAt: 1656766119687
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
# Get active visitors (last 5 minutes)
|
|
118
|
+
active = client.website_active_visitors("website_id")
|
|
119
|
+
|
|
120
|
+
# Get pageviews with time grouping
|
|
121
|
+
pageviews = client.website_pageviews("website_id", {
|
|
122
|
+
startAt: 1656679719687,
|
|
123
|
+
endAt: 1656766119687,
|
|
124
|
+
unit: "day",
|
|
125
|
+
timezone: "America/Los_Angeles"
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
# Get metrics by type
|
|
129
|
+
metrics = client.website_metrics("website_id", {
|
|
130
|
+
startAt: 1656679719687,
|
|
131
|
+
endAt: 1656766119687,
|
|
132
|
+
type: "browser" # or: path, referrer, os, device, country, etc.
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
# Get realtime stats (last 30 minutes)
|
|
136
|
+
realtime = client.realtime("website_id")
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Sending Events
|
|
140
|
+
|
|
141
|
+
Send custom events to Umami for tracking. This is useful for server-side event tracking.
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
client = Umami::Client.new
|
|
145
|
+
|
|
146
|
+
# Send a basic event
|
|
147
|
+
client.send_event({
|
|
148
|
+
website: "your-website-id",
|
|
149
|
+
url: "/checkout",
|
|
150
|
+
hostname: "example.com",
|
|
151
|
+
name: "purchase_completed"
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
# Send an event with custom data
|
|
155
|
+
client.send_event({
|
|
156
|
+
website: "your-website-id",
|
|
157
|
+
url: "/checkout",
|
|
158
|
+
hostname: "example.com",
|
|
159
|
+
name: "purchase_completed",
|
|
160
|
+
language: "en-US",
|
|
161
|
+
screen: "1920x1080",
|
|
162
|
+
title: "Checkout - Example Store",
|
|
163
|
+
data: {
|
|
164
|
+
order_id: "12345",
|
|
165
|
+
total: 99.99,
|
|
166
|
+
currency: "USD"
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
# Send with a custom User-Agent (optional)
|
|
171
|
+
client.send_event(payload, user_agent: "MyApp/1.0")
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Important notes about `send_event`:**
|
|
175
|
+
- No authentication token is sent (not required by the API)
|
|
176
|
+
- A `User-Agent` header is automatically included (required by Umami)
|
|
177
|
+
- For Umami Cloud, requests go to `https://cloud.umami.is/api/send` (different from other API calls)
|
|
178
|
+
- For self-hosted, requests go to your configured `uri_base`
|
|
179
|
+
|
|
180
|
+
### Sessions
|
|
181
|
+
|
|
182
|
+
```ruby
|
|
183
|
+
# Get sessions within a time range
|
|
184
|
+
sessions = client.website_sessions("website_id", {
|
|
185
|
+
startAt: 1656679719687,
|
|
186
|
+
endAt: 1656766119687,
|
|
187
|
+
page: 1,
|
|
188
|
+
pageSize: 20
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
# Get session statistics
|
|
192
|
+
stats = client.website_sessions_stats("website_id", {
|
|
193
|
+
startAt: 1656679719687,
|
|
194
|
+
endAt: 1656766119687
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
# Get individual session details
|
|
198
|
+
session = client.website_session("website_id", "session_id")
|
|
199
|
+
|
|
200
|
+
# Get session activity
|
|
201
|
+
activity = client.website_session_activity("website_id", "session_id", {
|
|
202
|
+
startAt: 1656679719687,
|
|
203
|
+
endAt: 1656766119687
|
|
204
|
+
})
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Events Data
|
|
208
|
+
|
|
209
|
+
```ruby
|
|
210
|
+
# Get paginated event list with search
|
|
211
|
+
events = client.website_events_list("website_id", {
|
|
212
|
+
startAt: 1656679719687,
|
|
213
|
+
endAt: 1656766119687,
|
|
214
|
+
search: "click",
|
|
215
|
+
page: 1,
|
|
216
|
+
pageSize: 20
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
# Get event data aggregations
|
|
220
|
+
event_data = client.website_event_data_events("website_id", {
|
|
221
|
+
startAt: 1656679719687,
|
|
222
|
+
endAt: 1656766119687
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
# Get event statistics
|
|
226
|
+
stats = client.website_event_data_stats("website_id", {
|
|
227
|
+
startAt: 1656679719687,
|
|
228
|
+
endAt: 1656766119687
|
|
229
|
+
})
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Reports
|
|
233
|
+
|
|
234
|
+
```ruby
|
|
235
|
+
# List reports (optionally filter by website and/or type)
|
|
236
|
+
all_reports = client.reports
|
|
237
|
+
website_reports = client.reports(websiteId: "website_id")
|
|
238
|
+
funnel_reports = client.reports(websiteId: "website_id", type: "funnel")
|
|
239
|
+
|
|
240
|
+
# Create a report
|
|
241
|
+
report = client.create_report({
|
|
242
|
+
websiteId: "website_id",
|
|
243
|
+
type: "funnel",
|
|
244
|
+
name: "Checkout Funnel",
|
|
245
|
+
parameters: {
|
|
246
|
+
startDate: "2024-01-01T00:00:00Z",
|
|
247
|
+
endDate: "2024-01-31T23:59:59Z"
|
|
248
|
+
}
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
# Run specialized reports
|
|
252
|
+
funnel = client.report_funnel({
|
|
253
|
+
websiteId: "website_id",
|
|
254
|
+
startDate: "2024-01-01T00:00:00Z",
|
|
255
|
+
endDate: "2024-01-31T23:59:59Z",
|
|
256
|
+
steps: [
|
|
257
|
+
{ type: "path", value: "/" },
|
|
258
|
+
{ type: "path", value: "/checkout" },
|
|
259
|
+
{ type: "path", value: "/thank-you" }
|
|
260
|
+
],
|
|
261
|
+
window: 7
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
retention = client.report_retention({
|
|
265
|
+
websiteId: "website_id",
|
|
266
|
+
startDate: "2024-01-01T00:00:00Z",
|
|
267
|
+
endDate: "2024-01-31T23:59:59Z",
|
|
268
|
+
timezone: "America/Los_Angeles"
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
# Available report types: attribution, breakdown, funnel, goal, journey, retention, revenue, utm
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**Report types:**
|
|
275
|
+
| Type | Description |
|
|
276
|
+
|------|-------------|
|
|
277
|
+
| `attribution` | Marketing channel attribution analysis |
|
|
278
|
+
| `breakdown` | Multi-dimensional data segmentation |
|
|
279
|
+
| `funnel` | Conversion funnel tracking |
|
|
280
|
+
| `goal` | Goal performance metrics |
|
|
281
|
+
| `journey` | User navigation path analysis |
|
|
282
|
+
| `retention` | Return visitor analysis |
|
|
283
|
+
| `revenue` | Revenue tracking and analysis |
|
|
284
|
+
| `utm` | UTM campaign parameter breakdown |
|
|
285
|
+
|
|
286
|
+
### User & Team Management
|
|
287
|
+
|
|
288
|
+
```ruby
|
|
289
|
+
# Get current user info
|
|
290
|
+
me = client.me
|
|
291
|
+
my_teams = client.my_teams(page: 1, pageSize: 10)
|
|
292
|
+
my_websites = client.my_websites(includeTeams: true)
|
|
293
|
+
|
|
294
|
+
# Team management
|
|
295
|
+
teams = client.teams
|
|
296
|
+
team = client.team("team_id")
|
|
297
|
+
client.create_team("My Team")
|
|
298
|
+
client.add_team_user("team_id", "user_id", "team-member")
|
|
299
|
+
|
|
300
|
+
# User management (admin only, self-hosted)
|
|
301
|
+
users = client.admin_users
|
|
302
|
+
client.create_user("username", "password", "user")
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Website Management
|
|
306
|
+
|
|
307
|
+
```ruby
|
|
308
|
+
# Create a website
|
|
309
|
+
website = client.create_website({
|
|
310
|
+
name: "My Website",
|
|
311
|
+
domain: "example.com",
|
|
312
|
+
teamId: "optional-team-id"
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
# Update a website
|
|
316
|
+
client.update_website("website_id", {
|
|
317
|
+
name: "Updated Name",
|
|
318
|
+
shareId: "public-share-id"
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
# Reset website data
|
|
322
|
+
client.reset_website("website_id")
|
|
323
|
+
|
|
324
|
+
# Delete a website
|
|
325
|
+
client.delete_website("website_id")
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Available Methods
|
|
329
|
+
|
|
330
|
+
### Authentication
|
|
331
|
+
- `verify_token` - Verify the current authentication token
|
|
332
|
+
|
|
333
|
+
### Me (Current User)
|
|
334
|
+
- `me` - Get current user information
|
|
335
|
+
- `my_teams(params)` - Get user's teams (supports pagination)
|
|
336
|
+
- `my_websites(params)` - Get user's websites
|
|
337
|
+
|
|
338
|
+
### Admin (Self-hosted only)
|
|
339
|
+
- `admin_users(params)` - List all users
|
|
340
|
+
- `admin_websites(params)` - List all websites
|
|
341
|
+
- `admin_teams(params)` - List all teams
|
|
342
|
+
|
|
343
|
+
### Users
|
|
344
|
+
- `create_user(username, password, role, id:)` - Create a user
|
|
345
|
+
- `user(user_id)` - Get user by ID
|
|
346
|
+
- `update_user(user_id, params)` - Update user
|
|
347
|
+
- `delete_user(user_id)` - Delete user
|
|
348
|
+
- `user_websites(user_id, params)` - Get user's websites
|
|
349
|
+
- `user_teams(user_id, params)` - Get user's teams
|
|
350
|
+
|
|
351
|
+
### Teams
|
|
352
|
+
- `teams(params)` - List all teams
|
|
353
|
+
- `create_team(name)` - Create a team
|
|
354
|
+
- `join_team(access_code)` - Join a team
|
|
355
|
+
- `team(team_id)` - Get team by ID
|
|
356
|
+
- `update_team(team_id, params)` - Update team
|
|
357
|
+
- `delete_team(team_id)` - Delete team
|
|
358
|
+
- `team_users(team_id, params)` - List team members
|
|
359
|
+
- `add_team_user(team_id, user_id, role)` - Add user to team
|
|
360
|
+
- `team_user(team_id, user_id)` - Get team member
|
|
361
|
+
- `update_team_user(team_id, user_id, role)` - Update member role
|
|
362
|
+
- `delete_team_user(team_id, user_id)` - Remove user from team
|
|
363
|
+
- `team_websites(team_id, params)` - List team websites
|
|
364
|
+
|
|
365
|
+
### Websites
|
|
366
|
+
- `websites(params)` - List all websites
|
|
367
|
+
- `create_website(params)` - Create a website
|
|
368
|
+
- `website(website_id)` - Get website by ID
|
|
369
|
+
- `update_website(website_id, params)` - Update website
|
|
370
|
+
- `delete_website(website_id)` - Delete website
|
|
371
|
+
- `reset_website(website_id)` - Reset website data
|
|
372
|
+
|
|
373
|
+
### Website Statistics
|
|
374
|
+
- `website_stats(website_id, params)` - Get statistics
|
|
375
|
+
- `website_active_visitors(website_id)` - Get active visitors
|
|
376
|
+
- `website_pageviews(website_id, params)` - Get pageviews
|
|
377
|
+
- `website_events(website_id, params)` - Get events (time-series)
|
|
378
|
+
- `website_events_series(website_id, params)` - Get events series
|
|
379
|
+
- `website_metrics(website_id, params)` - Get metrics
|
|
380
|
+
- `website_metrics_expanded(website_id, params)` - Get expanded metrics
|
|
381
|
+
|
|
382
|
+
### Sessions
|
|
383
|
+
- `website_sessions(website_id, params)` - List sessions
|
|
384
|
+
- `website_sessions_stats(website_id, params)` - Get session stats
|
|
385
|
+
- `website_sessions_weekly(website_id, params)` - Get weekly breakdown
|
|
386
|
+
- `website_session(website_id, session_id)` - Get session details
|
|
387
|
+
- `website_session_activity(website_id, session_id, params)` - Get activity
|
|
388
|
+
- `website_session_properties(website_id, session_id)` - Get properties
|
|
389
|
+
- `website_session_data_properties(website_id, params)` - Get data properties
|
|
390
|
+
- `website_session_data_values(website_id, params)` - Get data values
|
|
391
|
+
|
|
392
|
+
### Events
|
|
393
|
+
- `website_events_list(website_id, params)` - List events (paginated)
|
|
394
|
+
- `website_event_data(website_id, event_id)` - Get event data
|
|
395
|
+
- `website_event_data_events(website_id, params)` - Get event aggregations
|
|
396
|
+
- `website_event_data_fields(website_id, params)` - Get event fields
|
|
397
|
+
- `website_event_data_properties(website_id, params)` - Get event properties
|
|
398
|
+
- `website_event_data_values(website_id, params)` - Get event values
|
|
399
|
+
- `website_event_data_stats(website_id, params)` - Get event statistics
|
|
400
|
+
|
|
401
|
+
### Realtime
|
|
402
|
+
- `realtime(website_id)` - Get realtime stats (last 30 minutes)
|
|
403
|
+
|
|
404
|
+
### Links
|
|
405
|
+
- `links(params)` - List all links
|
|
406
|
+
- `link(link_id)` - Get link by ID
|
|
407
|
+
- `update_link(link_id, params)` - Update link
|
|
408
|
+
- `delete_link(link_id)` - Delete link
|
|
409
|
+
|
|
410
|
+
### Pixels
|
|
411
|
+
- `pixels(params)` - List all pixels
|
|
412
|
+
- `pixel(pixel_id)` - Get pixel by ID
|
|
413
|
+
- `update_pixel(pixel_id, params)` - Update pixel
|
|
414
|
+
- `delete_pixel(pixel_id)` - Delete pixel
|
|
415
|
+
|
|
416
|
+
### Reports
|
|
417
|
+
- `reports(params)` - List all reports (filter by `websiteId`, `type`)
|
|
418
|
+
- `create_report(params)` - Create a report
|
|
419
|
+
- `report(report_id)` - Get report by ID
|
|
420
|
+
- `update_report(report_id, params)` - Update report
|
|
421
|
+
- `delete_report(report_id)` - Delete report
|
|
422
|
+
- `report_attribution(params)` - Run attribution report
|
|
423
|
+
- `report_breakdown(params)` - Run breakdown report
|
|
424
|
+
- `report_funnel(params)` - Run funnel report
|
|
425
|
+
- `report_goals(params)` - Run goals report
|
|
426
|
+
- `report_journey(params)` - Run journey report
|
|
427
|
+
- `report_retention(params)` - Run retention report
|
|
428
|
+
- `report_revenue(params)` - Run revenue report
|
|
429
|
+
- `report_utm(params)` - Run UTM report
|
|
430
|
+
|
|
431
|
+
### Sending Events
|
|
432
|
+
- `send_event(payload, user_agent:)` - Send tracking event
|
|
433
|
+
|
|
90
434
|
## Error Handling
|
|
91
435
|
|
|
92
436
|
The gem defines several custom error classes:
|
|
93
437
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
-
|
|
438
|
+
```ruby
|
|
439
|
+
begin
|
|
440
|
+
client.website("non-existent-id")
|
|
441
|
+
rescue Umami::NotFoundError => e
|
|
442
|
+
puts "Website not found: #{e.message}"
|
|
443
|
+
rescue Umami::ClientError => e
|
|
444
|
+
puts "Client error: #{e.message}"
|
|
445
|
+
rescue Umami::ServerError => e
|
|
446
|
+
puts "Server error: #{e.message}"
|
|
447
|
+
rescue Umami::AuthenticationError => e
|
|
448
|
+
puts "Authentication failed: #{e.message}"
|
|
449
|
+
rescue Umami::ConfigurationError => e
|
|
450
|
+
puts "Configuration error: #{e.message}"
|
|
451
|
+
rescue Umami::APIError => e
|
|
452
|
+
puts "API error: #{e.message}"
|
|
453
|
+
end
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
**Error class hierarchy:**
|
|
457
|
+
- `Umami::Error` - Base error class
|
|
458
|
+
- `Umami::ConfigurationError` - Configuration issues
|
|
459
|
+
- `Umami::AuthenticationError` - Authentication failures
|
|
460
|
+
- `Umami::APIError` - API request failures
|
|
461
|
+
- `Umami::NotFoundError` - Resource not found (404)
|
|
462
|
+
- `Umami::ClientError` - Client errors (4xx)
|
|
463
|
+
- `Umami::ServerError` - Server errors (5xx)
|
|
97
464
|
|
|
98
465
|
## Logging
|
|
99
466
|
|
|
100
467
|
The gem uses a logger that can be configured:
|
|
101
468
|
|
|
102
469
|
```ruby
|
|
470
|
+
# Set log level
|
|
103
471
|
Umami.logger.level = Logger::DEBUG
|
|
472
|
+
|
|
473
|
+
# Use a custom logger
|
|
474
|
+
Umami.logger = Rails.logger
|
|
104
475
|
```
|
|
105
476
|
|
|
106
477
|
## Development
|
|
107
478
|
|
|
108
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake
|
|
479
|
+
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.
|
|
109
480
|
|
|
110
481
|
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
111
482
|
|
data/Rakefile
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "bundler/gem_tasks"
|
|
4
|
-
|
|
4
|
+
require "rake/testtask"
|
|
5
|
+
|
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
|
7
|
+
t.libs << "test"
|
|
8
|
+
t.libs << "lib"
|
|
9
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
|
10
|
+
t.warning = false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
task default: :test
|