analytics_ops 0.1.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 +7 -0
- data/CHANGELOG.md +47 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/CONTRIBUTING.md +67 -0
- data/LICENSE.txt +21 -0
- data/README.md +188 -0
- data/SECURITY.md +56 -0
- data/docs/api-support-matrix.md +50 -0
- data/docs/architecture.md +89 -0
- data/docs/authentication.md +86 -0
- data/docs/commands.md +112 -0
- data/docs/configuration-schema-v1.json +129 -0
- data/docs/configuration.md +167 -0
- data/docs/google-client-compatibility.md +59 -0
- data/docs/plan-format.md +89 -0
- data/docs/plan-schema-v1.json +224 -0
- data/docs/rails.md +73 -0
- data/docs/reports.md +124 -0
- data/docs/safety.md +93 -0
- data/docs/troubleshooting.md +103 -0
- data/exe/analytics-ops +6 -0
- data/lib/analytics_ops/applier.rb +52 -0
- data/lib/analytics_ops/canonical.rb +65 -0
- data/lib/analytics_ops/cli.rb +427 -0
- data/lib/analytics_ops/clients/admin.rb +446 -0
- data/lib/analytics_ops/clients/data.rb +314 -0
- data/lib/analytics_ops/configuration/document.rb +25 -0
- data/lib/analytics_ops/configuration/loader.rb +76 -0
- data/lib/analytics_ops/configuration/schema.rb +107 -0
- data/lib/analytics_ops/configuration/validator.rb +344 -0
- data/lib/analytics_ops/configuration.rb +19 -0
- data/lib/analytics_ops/desired_state.rb +40 -0
- data/lib/analytics_ops/errors.rb +31 -0
- data/lib/analytics_ops/plan.rb +551 -0
- data/lib/analytics_ops/planner.rb +233 -0
- data/lib/analytics_ops/rails/railtie.rb +65 -0
- data/lib/analytics_ops/rails.rb +5 -0
- data/lib/analytics_ops/redaction.rb +46 -0
- data/lib/analytics_ops/reports/catalog.rb +100 -0
- data/lib/analytics_ops/reports/definition.rb +226 -0
- data/lib/analytics_ops/reports/result.rb +90 -0
- data/lib/analytics_ops/reports.rb +13 -0
- data/lib/analytics_ops/resources.rb +79 -0
- data/lib/analytics_ops/snapshot.rb +45 -0
- data/lib/analytics_ops/version.rb +5 -0
- data/lib/analytics_ops/workspace.rb +212 -0
- data/lib/analytics_ops.rb +21 -0
- data/lib/generators/analytics_ops/install_generator.rb +23 -0
- data/lib/generators/analytics_ops/templates/analytics-ops +9 -0
- data/lib/generators/analytics_ops/templates/analytics_ops.yml +23 -0
- data/sig/analytics_ops.rbs +395 -0
- metadata +131 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 3bf17db3adc805f77cf7d22e2ea2840a3eaf44a007be8036a48bf58a4d2d3a36
|
|
4
|
+
data.tar.gz: 1642e17fb59a976a471636a92f8da2f1290c3e13eb7bee515722efd8315a2e4a
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c934c5e8856505c2ec5d8e4311ac9f9e3d23ba47078fc478170dcda4d08e5d5be990402fa2795d56138ba30d2c8e92dbe368fdb1fb3da254bead9ba429338f09
|
|
7
|
+
data.tar.gz: b96a8112f501416f763d3528419435e2364526f66cd43266ec3880825f61c964550eca739ece89607d7d89a583051b44d35d1f3f62a018260dab625d13a871ef
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Analytics Ops follows Semantic Versioning for its public Ruby, CLI,
|
|
4
|
+
configuration, and plan contracts.
|
|
5
|
+
|
|
6
|
+
## [0.1.0] - 2026-07-22
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- Strict version-1 YAML configuration with safe Psych parsing, no ERB or
|
|
11
|
+
aliases, a 1 MiB limit, allowlisted environment interpolation, fail-closed
|
|
12
|
+
keys, quoted numeric identifiers, and committed JSON Schema.
|
|
13
|
+
- Immutable desired state, normalized Admin resources, canonical JSON,
|
|
14
|
+
snapshot fingerprints, and deterministic planning.
|
|
15
|
+
- Version-1 saved plans with strict scalar/payload/identity validation,
|
|
16
|
+
duplicate-key and secret-field rejection, cross-property protection,
|
|
17
|
+
atomic mode-0600 writes, and committed JSON Schema.
|
|
18
|
+
- Create/update-only planning for web stream default URI, retention, key
|
|
19
|
+
events, custom dimensions, and custom metrics. Unmanaged resources are never
|
|
20
|
+
deleted or archived.
|
|
21
|
+
- Explicit guarded apply with saved-plan-only execution, fresh snapshot
|
|
22
|
+
validation, stale-plan rejection, stop-on-first-failure behavior, and
|
|
23
|
+
structured partial reconciliation.
|
|
24
|
+
- Lazy official Google Admin and Data adapters, typed/redacted errors,
|
|
25
|
+
deterministic protobuf contract tests, and no generated types in public
|
|
26
|
+
results.
|
|
27
|
+
- `doctor`, `discover`, `snapshot`, `audit`, `plan`, `apply`,
|
|
28
|
+
`verify`, `report`, `realtime`, and `schema` CLI commands.
|
|
29
|
+
- Human, automation-safe JSON, and report-only CSV output with stable exit
|
|
30
|
+
statuses.
|
|
31
|
+
- Immutable standard/realtime report definitions, normalized result metadata
|
|
32
|
+
and quota information, and seven built-in commercial recipes.
|
|
33
|
+
- Optional Rails 7.2–8.1 Railtie, install generator, binstub, and read-only
|
|
34
|
+
operator Rake tasks.
|
|
35
|
+
- Public RBS signatures, security/redaction checks, Ruby 3.2–4.0 CI, Rails
|
|
36
|
+
compatibility jobs, package inspection, dependency audit, and OIDC Trusted
|
|
37
|
+
Publishing workflow.
|
|
38
|
+
- Complete operator, safety, report, Rails, architecture, compatibility, and
|
|
39
|
+
troubleshooting documentation.
|
|
40
|
+
|
|
41
|
+
### Security
|
|
42
|
+
|
|
43
|
+
- Requiring the gem, loading configuration, and booting Rails perform no
|
|
44
|
+
network I/O.
|
|
45
|
+
- Credentials and report rows are excluded from configuration and plan
|
|
46
|
+
contracts; common credential patterns are redacted from errors.
|
|
47
|
+
- Ordinary plans cannot delete or archive resources.
|
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
"analytics_ops" follows [The Ruby Community Conduct Guideline](https://www.ruby-lang.org/en/conduct) in all "collaborative space", which is defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.):
|
|
4
|
+
|
|
5
|
+
* Participants will be tolerant of opposing views.
|
|
6
|
+
* Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
|
|
7
|
+
* When interpreting the words and actions of others, participants should always assume good intentions.
|
|
8
|
+
* Behaviour which can be reasonably considered harassment will not be tolerated.
|
|
9
|
+
|
|
10
|
+
If you have any concerns about behaviour within this project, please contact us at ["nelsonchavespro@gmail.com"](mailto:"nelsonchavespro@gmail.com").
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thank you for helping make Analytics Ops safer and easier to operate.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/nelsonchaves/analytics_ops.git
|
|
9
|
+
cd analytics_ops
|
|
10
|
+
bin/setup
|
|
11
|
+
bin/check
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Useful focused commands:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
bundle exec rspec spec/analytics_ops/clients/data_spec.rb
|
|
18
|
+
bundle exec rubocop
|
|
19
|
+
bundle exec rbs -I sig validate
|
|
20
|
+
bundle exec rake build
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Use `RSPEC_STATUS_FILE=/tmp/analytics_ops-rspec-status` when the repository is
|
|
24
|
+
mounted read-only except for source edits.
|
|
25
|
+
|
|
26
|
+
## Design rules
|
|
27
|
+
|
|
28
|
+
- Keep the core plain Ruby and independent of Rails and Active Support.
|
|
29
|
+
- Use Google's official Ruby clients; do not add another HTTP or OAuth stack.
|
|
30
|
+
- Keep generated Google objects behind adapters.
|
|
31
|
+
- Do not introduce telemetry, a database, browser analytics, or boot-time
|
|
32
|
+
network access.
|
|
33
|
+
- Preserve the read-only default and saved-plan confirmation boundary.
|
|
34
|
+
- Do not add ordinary delete/archive operations.
|
|
35
|
+
- Use immutable gem-owned public values and typed errors.
|
|
36
|
+
|
|
37
|
+
## Tests
|
|
38
|
+
|
|
39
|
+
Use RSpec. Run focused specs while changing a subsystem, then run the complete
|
|
40
|
+
suite before the milestone commit. Ordinary tests must use injected fakes and
|
|
41
|
+
must never contact a real property.
|
|
42
|
+
|
|
43
|
+
An opt-in live check may use only a dedicated disposable GA4 property. It must
|
|
44
|
+
use uniquely prefixed resources and clean up only resources it created. Never
|
|
45
|
+
run a live test against production.
|
|
46
|
+
|
|
47
|
+
Changes to a Google adapter need request/response coercion tests against the
|
|
48
|
+
supported official generated classes. Changes to planning need deterministic
|
|
49
|
+
output, stale-state, cross-property, and idempotency coverage.
|
|
50
|
+
|
|
51
|
+
## Pull requests
|
|
52
|
+
|
|
53
|
+
Keep commits focused and explain:
|
|
54
|
+
|
|
55
|
+
- the user-visible problem and public contract
|
|
56
|
+
- read/write behavior and rollback implications
|
|
57
|
+
- tests and compatibility checks performed
|
|
58
|
+
- documentation or schema changes
|
|
59
|
+
|
|
60
|
+
Update `CHANGELOG.md` and the relevant support matrix when behavior changes.
|
|
61
|
+
Configuration and plan incompatibilities require an explicit schema version;
|
|
62
|
+
they never migrate silently.
|
|
63
|
+
|
|
64
|
+
Never commit credentials, real property exports, visitor data, production
|
|
65
|
+
plans, or production identifiers. Follow [SECURITY.md](SECURITY.md) for private
|
|
66
|
+
vulnerability reports and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for project
|
|
67
|
+
conduct.
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nelson Chaves
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# Analytics Ops
|
|
2
|
+
|
|
3
|
+
**Google Analytics 4 configuration as code and reporting for Ruby and Rails.**
|
|
4
|
+
|
|
5
|
+
Analytics Ops gives you a review-first way to inspect GA4, detect drift, run
|
|
6
|
+
useful reports, and apply a small set of safe configuration changes. The core
|
|
7
|
+
is plain Ruby; Rails support is optional.
|
|
8
|
+
|
|
9
|
+
## Five-minute read-only start
|
|
10
|
+
|
|
11
|
+
You need Ruby 3.2 or newer, a GA4 property you can read, and the
|
|
12
|
+
[Google Cloud CLI](https://cloud.google.com/sdk/docs/install).
|
|
13
|
+
|
|
14
|
+
1. Add Analytics Ops to your bundle:
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
# Gemfile
|
|
18
|
+
gem "analytics_ops", "~> 0.1", group: :development
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
bundle install
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
2. Enable the Google Analytics Admin API and Data API in your own Google Cloud
|
|
26
|
+
project, then create local Application Default Credentials:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
gcloud auth application-default login \
|
|
30
|
+
--scopes="https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/analytics.readonly"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
3. Create `config/analytics_ops.yml`:
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
version: 1
|
|
37
|
+
|
|
38
|
+
profiles:
|
|
39
|
+
production:
|
|
40
|
+
property_id: "123456789"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
4. Check access without changing anything:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
bundle exec analytics-ops doctor
|
|
47
|
+
bundle exec analytics-ops discover
|
|
48
|
+
bundle exec analytics-ops audit
|
|
49
|
+
bundle exec analytics-ops report traffic_acquisition
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Every command above is read-only. `audit` exits with status 2 when it finds
|
|
53
|
+
drift, which makes it useful in CI.
|
|
54
|
+
|
|
55
|
+
## The safe change workflow
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
configuration → audit → saved plan → review → apply → verify
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Read-only: save a deterministic plan with mode 0600
|
|
63
|
+
bundle exec analytics-ops plan --output tmp/ga4-plan.json
|
|
64
|
+
|
|
65
|
+
# Review the JSON before doing anything
|
|
66
|
+
less tmp/ga4-plan.json
|
|
67
|
+
|
|
68
|
+
# Mutating: prints the exact saved operations and asks you to type yes
|
|
69
|
+
bundle exec analytics-ops apply tmp/ga4-plan.json
|
|
70
|
+
|
|
71
|
+
# Read-only: confirm managed settings now match
|
|
72
|
+
bundle exec analytics-ops verify
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`apply` refreshes the remote snapshot, rejects stale plans, and executes only
|
|
76
|
+
the operations in the saved file. Ordinary plans never delete or archive
|
|
77
|
+
anything. If one operation fails, execution stops and reports what succeeded,
|
|
78
|
+
what failed, and what remains.
|
|
79
|
+
|
|
80
|
+
## Common commands
|
|
81
|
+
|
|
82
|
+
| Command | Purpose | Remote writes? |
|
|
83
|
+
| --- | --- | --- |
|
|
84
|
+
| `analytics-ops doctor` | Check configuration, credentials, APIs, property access, clients, and clock | No |
|
|
85
|
+
| `analytics-ops discover` | List accessible accounts, properties, and streams | No |
|
|
86
|
+
| `analytics-ops snapshot` | Print normalized managed remote state | No |
|
|
87
|
+
| `analytics-ops audit` | Show drift without writing a plan file | No |
|
|
88
|
+
| `analytics-ops plan --output FILE` | Review and save deterministic changes | No |
|
|
89
|
+
| `analytics-ops apply FILE` | Apply one reviewed, non-stale plan | **Yes** |
|
|
90
|
+
| `analytics-ops verify` | Check convergence | No |
|
|
91
|
+
| `analytics-ops report NAME` | Run a built-in standard report | No |
|
|
92
|
+
| `analytics-ops realtime` | Run the realtime-events report | No |
|
|
93
|
+
| `analytics-ops schema --format json` | Print the configuration schema | No |
|
|
94
|
+
|
|
95
|
+
Use `--format json` for automation. CSV is available only for reports:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
bundle exec analytics-ops report landing_pages --format csv
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
See [Commands](docs/commands.md) for every option and exit status.
|
|
102
|
+
|
|
103
|
+
## IDs: the quick distinction
|
|
104
|
+
|
|
105
|
+
Use fake values like these in examples and tests:
|
|
106
|
+
|
|
107
|
+
| Value | Example | Where it belongs |
|
|
108
|
+
| --- | --- | --- |
|
|
109
|
+
| Account ID | `100000001` | Discovery output only |
|
|
110
|
+
| Property ID | `123456789` | `property_id` in configuration and API requests |
|
|
111
|
+
| Stream ID | `987654321` | `stream_id` in configuration |
|
|
112
|
+
| Measurement ID | `G-EXAMPLE1` | Browser tagging; never use it as a stream ID |
|
|
113
|
+
| OAuth client | A Cloud project client ID/secret | Owned by your application, never this YAML |
|
|
114
|
+
| Service-account identity | `ga-reader@example-project.iam.gserviceaccount.com` | Granted GA access; its key is never this YAML |
|
|
115
|
+
|
|
116
|
+
## Ruby API
|
|
117
|
+
|
|
118
|
+
```ruby
|
|
119
|
+
workspace = AnalyticsOps::Workspace.load(
|
|
120
|
+
"config/analytics_ops.yml",
|
|
121
|
+
profile: "production"
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
plan = workspace.plan
|
|
125
|
+
plan.write("tmp/ga4-plan.json")
|
|
126
|
+
|
|
127
|
+
report = workspace.report("calculator_completions")
|
|
128
|
+
report.rows.each { |row| puts row.fetch("eventCount") }
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Loading the gem, loading YAML, and booting Rails do not contact Google.
|
|
132
|
+
Network calls happen only when a workspace operation is invoked.
|
|
133
|
+
|
|
134
|
+
## Rails
|
|
135
|
+
|
|
136
|
+
```ruby
|
|
137
|
+
# Gemfile
|
|
138
|
+
gem "analytics_ops", require: "analytics_ops/rails", group: :development
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
bin/rails generate analytics_ops:install
|
|
143
|
+
bin/rake analytics:doctor
|
|
144
|
+
bin/rake 'analytics:report[traffic_acquisition]'
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The integration is a Railtie, not an Engine. It adds a generator and operator
|
|
148
|
+
Rake tasks—no models, migrations, routes, controllers, views, JavaScript, or
|
|
149
|
+
boot-time network calls. See [Rails integration](docs/rails.md).
|
|
150
|
+
|
|
151
|
+
## What Analytics Ops does not do
|
|
152
|
+
|
|
153
|
+
- It does not inject browser analytics or manage consent banners.
|
|
154
|
+
- It does not store credentials, tokens, report rows, or local state.
|
|
155
|
+
- It does not delete accounts, properties, streams, or unmanaged resources.
|
|
156
|
+
- It does not claim to manage settings that Google exposes only in the UI.
|
|
157
|
+
- Experimental declarations are findings only in version 0.1.0; they are not
|
|
158
|
+
silently applied through Alpha APIs.
|
|
159
|
+
|
|
160
|
+
## Documentation
|
|
161
|
+
|
|
162
|
+
| Guide | Topic |
|
|
163
|
+
| --- | --- |
|
|
164
|
+
| [Authentication](docs/authentication.md) | ADC, scopes, service accounts, and safe automation |
|
|
165
|
+
| [Configuration](docs/configuration.md) | Complete strict YAML contract |
|
|
166
|
+
| [Commands](docs/commands.md) | CLI syntax, formats, and exit statuses |
|
|
167
|
+
| [Reports](docs/reports.md) | Built-in recipes and GA reporting limitations |
|
|
168
|
+
| [Rails](docs/rails.md) | Generator and Rake tasks |
|
|
169
|
+
| [Safety](docs/safety.md) | Plans, stale-state protection, rollback, and credentials |
|
|
170
|
+
| [Plan format](docs/plan-format.md) | Version-1 JSON contract |
|
|
171
|
+
| [API support](docs/api-support-matrix.md) | Exactly what is managed, manual, or unsupported |
|
|
172
|
+
| [Client compatibility](docs/google-client-compatibility.md) | Tested official Google gem versions |
|
|
173
|
+
| [Troubleshooting](docs/troubleshooting.md) | Common failures and fixes |
|
|
174
|
+
| [Architecture](docs/architecture.md) | Boundaries and data flow |
|
|
175
|
+
|
|
176
|
+
For development, run:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
bin/setup
|
|
180
|
+
bin/check
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Security issues belong in private vulnerability reporting; see
|
|
184
|
+
[SECURITY.md](SECURITY.md). Contributions follow [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
185
|
+
|
|
186
|
+
Analytics Ops is MIT licensed and is not affiliated with, sponsored by, or
|
|
187
|
+
endorsed by Google LLC. Google Analytics is a trademark of Google LLC and is
|
|
188
|
+
named only to describe API compatibility.
|
data/SECURITY.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Analytics Ops is pre-release. Security fixes currently target the latest
|
|
6
|
+
commit on `master`. A published support table will replace this section before
|
|
7
|
+
1.0.
|
|
8
|
+
|
|
9
|
+
## Report privately
|
|
10
|
+
|
|
11
|
+
Do not open a public issue for a vulnerability or exposed credential. Use
|
|
12
|
+
GitHub's private vulnerability reporting for this repository.
|
|
13
|
+
|
|
14
|
+
Include:
|
|
15
|
+
|
|
16
|
+
- affected version or commit
|
|
17
|
+
- smallest safe reproduction
|
|
18
|
+
- expected and observed behavior
|
|
19
|
+
- potential impact
|
|
20
|
+
- whether a disposable or production property was involved
|
|
21
|
+
|
|
22
|
+
Do not include credentials, access or refresh tokens, authorization headers,
|
|
23
|
+
private keys, visitor data, report exports, or production plan files.
|
|
24
|
+
|
|
25
|
+
If credentials may be exposed, revoke or rotate them with Google immediately;
|
|
26
|
+
do not wait for a project response.
|
|
27
|
+
|
|
28
|
+
## Security guarantees
|
|
29
|
+
|
|
30
|
+
Analytics Ops:
|
|
31
|
+
|
|
32
|
+
- uses Application Default Credentials or an explicitly injected Google
|
|
33
|
+
credential object
|
|
34
|
+
- refuses credential-shaped configuration and plan fields
|
|
35
|
+
- redacts common authorization material from translated errors
|
|
36
|
+
- performs no network I/O while requiring the gem, loading YAML, or booting
|
|
37
|
+
Rails
|
|
38
|
+
- defaults to read-only commands
|
|
39
|
+
- requires a strictly validated saved plan and explicit confirmation to mutate
|
|
40
|
+
- rejects stale and cross-property plans
|
|
41
|
+
- excludes delete/archive operations from ordinary plans
|
|
42
|
+
- never logs report results automatically
|
|
43
|
+
- has no telemetry, credential store, database, or browser injection
|
|
44
|
+
- publishes through RubyGems Trusted Publishing without a stored API key
|
|
45
|
+
|
|
46
|
+
Plan files still describe operational configuration and are created with mode
|
|
47
|
+
0600. Report output may contain sensitive aggregate data and should be handled
|
|
48
|
+
under the operator's data policy.
|
|
49
|
+
|
|
50
|
+
## Operator responsibilities
|
|
51
|
+
|
|
52
|
+
Analytics Ops cannot secure an overprivileged Cloud project, service account,
|
|
53
|
+
GitHub organization, CI runner, GA property, or exported report. Use
|
|
54
|
+
least-privilege read credentials for routine work, isolate mutation
|
|
55
|
+
credentials, protect release environments, and keep production mutation
|
|
56
|
+
credentials out of Rails web containers.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# API support matrix
|
|
2
|
+
|
|
3
|
+
This matrix describes Analytics Ops 0.1.0—not every method Google exposes.
|
|
4
|
+
|
|
5
|
+
| State | Meaning |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| Managed | Read and safely create/update within the stated limit |
|
|
8
|
+
| Audited | Read-only |
|
|
9
|
+
| Experimental | Explicitly declared, but Alpha behavior is isolated and may change |
|
|
10
|
+
| Manual | Reported as an operator checklist |
|
|
11
|
+
| Unsupported | Deliberately outside the public contract |
|
|
12
|
+
|
|
13
|
+
| Capability | State | Exact 0.1.0 behavior |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| Account/property discovery | Audited | Lists accessible summaries |
|
|
16
|
+
| Data-stream discovery | Audited | Lists web, Android, and iOS streams |
|
|
17
|
+
| Web stream default URI | Managed | Updates an existing web stream |
|
|
18
|
+
| Stream create/delete | Unsupported | Missing streams become findings |
|
|
19
|
+
| Data retention | Managed | Reads and updates supported periods/reset behavior |
|
|
20
|
+
| Key events | Managed | Reads and creates missing events; no delete |
|
|
21
|
+
| Custom dimensions | Managed | Reads, creates, and updates display name/description; user ads flag where supported |
|
|
22
|
+
| Custom metrics | Managed | Reads, creates, and updates display name/description |
|
|
23
|
+
| Standard Data API reports | Audited | Immutable definitions and normalized results |
|
|
24
|
+
| Realtime Data API reports | Audited | Immutable definitions and normalized results |
|
|
25
|
+
| Batch reports | Unsupported | Use individual definitions |
|
|
26
|
+
| Enhanced Measurement | Experimental | Validated declaration and finding only; no mutation |
|
|
27
|
+
| Google Signals | Experimental | Validated declaration and finding only; no mutation |
|
|
28
|
+
| Consent coverage | Manual | Must be verified in tagging/consent systems |
|
|
29
|
+
| Ads-personalization regions | Manual | Not inferred from similarly named API fields |
|
|
30
|
+
| Stream data redaction | Manual | UI/API policy must be verified separately |
|
|
31
|
+
| User-provided data setting | Unsupported | Not read or changed |
|
|
32
|
+
| Event create/edit rules | Unsupported | Alpha, outside 0.1.0 |
|
|
33
|
+
| Audiences and expanded datasets | Unsupported | Alpha, outside 0.1.0 |
|
|
34
|
+
| Google Ads, AdSense, DV360, SA360 links | Unsupported | Not read or changed |
|
|
35
|
+
| BigQuery links | Unsupported | Not read or changed |
|
|
36
|
+
| Access bindings | Unsupported | Not read or changed |
|
|
37
|
+
| Measurement Protocol secrets/events | Unsupported | Never managed |
|
|
38
|
+
| Account/property/stream deletion | Unsupported | No destructive path |
|
|
39
|
+
|
|
40
|
+
Google marks some Admin API capabilities as Alpha and warns that Alpha
|
|
41
|
+
contracts may break. Analytics Ops never labels a capability managed merely
|
|
42
|
+
because a generated class exists. The supported operations above have
|
|
43
|
+
executable protobuf-coercion contract specs against the pinned official Ruby
|
|
44
|
+
clients.
|
|
45
|
+
|
|
46
|
+
References:
|
|
47
|
+
|
|
48
|
+
- [Google Analytics Admin API overview](https://developers.google.com/analytics/devguides/config/admin/v1)
|
|
49
|
+
- [Google Analytics Data API](https://developers.google.com/analytics/devguides/reporting/data/v1)
|
|
50
|
+
- [Google Analytics Admin API changelog](https://developers.google.com/analytics/devguides/config/admin/v1/changelog)
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
Analytics Ops is a plain-Ruby library and CLI with optional Rails hooks. It has
|
|
4
|
+
no database and keeps Google's generated classes behind two narrow adapters.
|
|
5
|
+
|
|
6
|
+
```text
|
|
7
|
+
strict YAML
|
|
8
|
+
→ immutable desired state
|
|
9
|
+
→ Admin API snapshot
|
|
10
|
+
→ deterministic planner
|
|
11
|
+
→ versioned saved plan
|
|
12
|
+
→ explicit guarded apply
|
|
13
|
+
→ convergence verification
|
|
14
|
+
|
|
15
|
+
immutable report definition
|
|
16
|
+
→ Data API adapter
|
|
17
|
+
→ immutable normalized result
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Core objects
|
|
21
|
+
|
|
22
|
+
| Object | Responsibility |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| `Configuration` | Bounded safe YAML, environment interpolation, schema validation |
|
|
25
|
+
| `DesiredState` | Immutable configuration for one profile |
|
|
26
|
+
| `Resources` | Gem-owned account/property/stream/settings values |
|
|
27
|
+
| `Snapshot` | Canonical managed remote state and SHA-256 fingerprint |
|
|
28
|
+
| `Planner` | Pure desired-versus-snapshot comparison; no client access |
|
|
29
|
+
| `Plan` | Strict deterministic JSON mutation contract |
|
|
30
|
+
| `Applier` | Confirmation, fresh-snapshot check, sequential saved operations |
|
|
31
|
+
| `Clients::Admin` | Official Admin request translation and response normalization |
|
|
32
|
+
| `Reports::Definition` | Strict immutable Data API query |
|
|
33
|
+
| `Clients::Data` | Standard/realtime request translation and result normalization |
|
|
34
|
+
| `Workspace` | Public orchestration API with independently injectable clients |
|
|
35
|
+
| `CLI` | Option validation, formats, stable statuses, and explicit confirmation |
|
|
36
|
+
| `Railtie` | Optional generator and operator Rake tasks |
|
|
37
|
+
|
|
38
|
+
## Dependency direction
|
|
39
|
+
|
|
40
|
+
Domain and planning code know nothing about protobufs, gRPC, Rails, Active
|
|
41
|
+
Support, OAuth flows, or HTTP transports. Admin and Data adapters translate
|
|
42
|
+
official generated values immediately into immutable Analytics Ops values.
|
|
43
|
+
The adapters can be injected independently, so tests use deterministic fakes.
|
|
44
|
+
|
|
45
|
+
The core requires Google's wrapper gems lazily. Requiring `analytics_ops`
|
|
46
|
+
defines classes only; it does not instantiate a client or discover ADC.
|
|
47
|
+
|
|
48
|
+
## State model
|
|
49
|
+
|
|
50
|
+
Google Analytics is the remote source of truth. There is no local state
|
|
51
|
+
database. The configuration declares desired state and a snapshot captures the
|
|
52
|
+
relevant remote state. Canonical key ordering and normalized arrays make
|
|
53
|
+
snapshot fingerprints and plan bytes deterministic.
|
|
54
|
+
|
|
55
|
+
Apply accepts an already validated plan, refreshes the snapshot, compares its
|
|
56
|
+
fingerprint, then sends only the saved operations. A partial response is
|
|
57
|
+
explicit reconciliation data, not a hidden retry or rollback.
|
|
58
|
+
|
|
59
|
+
## Error boundary
|
|
60
|
+
|
|
61
|
+
Expected failures become typed Analytics Ops errors:
|
|
62
|
+
|
|
63
|
+
- configuration and invalid plan
|
|
64
|
+
- authentication and authorization
|
|
65
|
+
- unsupported capability and identity conflict
|
|
66
|
+
- stale plan and confirmation required
|
|
67
|
+
- quota, timeout, invalid request, and remote failure
|
|
68
|
+
- partial apply with a structured result
|
|
69
|
+
|
|
70
|
+
Messages are redacted before user-visible output. Callers do not need to parse
|
|
71
|
+
Google exception text.
|
|
72
|
+
|
|
73
|
+
An injected logger receives small JSON request events containing only the
|
|
74
|
+
service method and target resource. Request bodies, authorization data, and
|
|
75
|
+
report results are never logged automatically. CLI logging defaults to
|
|
76
|
+
`warn`.
|
|
77
|
+
|
|
78
|
+
## Rails boundary
|
|
79
|
+
|
|
80
|
+
`require "analytics_ops/rails"` adds a Railtie only. It does not add an
|
|
81
|
+
Engine, model, migration, route, controller, view, asset, or boot-time network
|
|
82
|
+
call. Browser analytics and consent remain application concerns.
|
|
83
|
+
|
|
84
|
+
## Experimental boundary
|
|
85
|
+
|
|
86
|
+
Google identifies certain Admin capabilities as Alpha. Version 0.1.0 accepts
|
|
87
|
+
explicit Enhanced Measurement and Google Signals declarations only so they can
|
|
88
|
+
appear as experimental findings. It does not apply them. Stable/beta
|
|
89
|
+
operations do not depend on an experimental public Analytics Ops contract.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Authentication
|
|
2
|
+
|
|
3
|
+
Analytics Ops uses [Google Application Default Credentials (ADC)](https://cloud.google.com/docs/authentication/application-default-credentials)
|
|
4
|
+
through Google's official Ruby clients. It does not implement OAuth, store
|
|
5
|
+
tokens, or accept credential fields in configuration.
|
|
6
|
+
|
|
7
|
+
## Local read-only use
|
|
8
|
+
|
|
9
|
+
Use an identity that has read access to the target GA4 property:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
gcloud auth application-default login \
|
|
13
|
+
--scopes="https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/analytics.readonly"
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Enable both APIs in the Google Cloud project used for authentication:
|
|
17
|
+
|
|
18
|
+
- Google Analytics Admin API
|
|
19
|
+
- Google Analytics Data API
|
|
20
|
+
|
|
21
|
+
Then run:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
analytics-ops doctor
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`doctor` makes small read-only calls to both APIs. It confirms that Google
|
|
28
|
+
accepts the credentials and that the property can be read. The installed
|
|
29
|
+
clients do not expose a reliable contract for inspecting the scopes inside an
|
|
30
|
+
already-issued token, so `doctor` reports scope inspection as `unknown`
|
|
31
|
+
instead of guessing.
|
|
32
|
+
|
|
33
|
+
## Applying changes
|
|
34
|
+
|
|
35
|
+
Read-only credentials cannot apply a plan. Use a separately protected identity
|
|
36
|
+
with the `analytics.edit` scope and sufficient access to the GA4 property:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
gcloud auth application-default login \
|
|
40
|
+
--scopes="https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/analytics.readonly,https://www.googleapis.com/auth/analytics.edit"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Keep mutation credentials out of a deployed Rails web container. Apply plans
|
|
44
|
+
from an administrator workstation or a protected release job.
|
|
45
|
+
|
|
46
|
+
## Automation
|
|
47
|
+
|
|
48
|
+
Prefer one of these:
|
|
49
|
+
|
|
50
|
+
- A dedicated service account with only the GA properties and roles it needs.
|
|
51
|
+
- Workload Identity Federation, which avoids a long-lived JSON key.
|
|
52
|
+
- An explicitly injected Google credentials object when using the Ruby API.
|
|
53
|
+
|
|
54
|
+
Cloud IAM permission alone does not grant access to a GA4 property. Add the
|
|
55
|
+
service-account identity—such as
|
|
56
|
+
`ga-reader@example-project.iam.gserviceaccount.com`—to the property with the
|
|
57
|
+
appropriate Google Analytics role.
|
|
58
|
+
|
|
59
|
+
## Values that are easy to confuse
|
|
60
|
+
|
|
61
|
+
| Value | Example | Meaning |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| Property ID | `123456789` | Numeric GA4 property identifier used by Admin and Data APIs |
|
|
64
|
+
| Stream ID | `987654321` | Numeric data-stream resource identifier |
|
|
65
|
+
| Measurement ID | `G-EXAMPLE1` | Web tagging identifier; not accepted as `property_id` or `stream_id` |
|
|
66
|
+
| Account ID | `100000001` | Numeric Analytics account identifier shown by discovery |
|
|
67
|
+
| OAuth client | Client ID and secret in your Cloud project | Starts a user OAuth flow; never put it in Analytics Ops YAML |
|
|
68
|
+
| Service account | An IAM email identity | Receives GA property access; a JSON private key is credential material |
|
|
69
|
+
|
|
70
|
+
## Credential rules
|
|
71
|
+
|
|
72
|
+
- Never put credentials, paths to credentials, access tokens, refresh tokens,
|
|
73
|
+
private keys, API keys, or OAuth secrets in `analytics_ops.yml`.
|
|
74
|
+
- Never put credentials in a saved plan.
|
|
75
|
+
- Never commit service-account JSON.
|
|
76
|
+
- Never paste credentials into an issue, fixture, log, or report.
|
|
77
|
+
- Revoke or rotate credentials immediately after suspected exposure.
|
|
78
|
+
- Do not create a shared public OAuth client for this gem.
|
|
79
|
+
|
|
80
|
+
Analytics Ops redacts common credential patterns from translated errors, but
|
|
81
|
+
redaction is a final safety net—not a safe way to handle secrets.
|
|
82
|
+
|
|
83
|
+
Official Google setup references:
|
|
84
|
+
|
|
85
|
+
- [Admin API quickstart](https://developers.google.com/analytics/devguides/config/admin/v1/quickstart)
|
|
86
|
+
- [Data API quickstart](https://developers.google.com/analytics/devguides/reporting/data/v1/quickstart-client-libraries)
|