Overview
Metriquality ingests three signal streams from your studio — developer velocity (Jira/GitHub), player sentiment (Discord), and player telemetry — correlates them against live competitor market signals, and emits a single executable recommendation with measured impact (incremental lift measured via holdout / geo-split where available).
This guide walks from zero to your first recommendation in three steps. You'll need: your studio's credentials (delivered by email at signup), and admin access to your Jira/GitHub org and Discord server.
Step 1 — Connect Webhooks
Each credential email includes three webhook endpoints. Configure whichever signals you want to use:
Jira
In Jira: Project Settings → Webhooks → Create Webhook. Set the URL to your jira_endpoint and enable events: Sprint started, Sprint closed, Issue resolved. Set the secret header X-Jira-Signature to your jira_webhook_secret.
GitHub
In your repo: Settings → Webhooks → Add Webhook. Set the Payload URL to your github_endpoint. Content type: application/json. Secret: your github_webhook_secret. Events: Pull requests, Issues.
Discord
In your server: any bot or webhook integration that can POST messages to your discord_endpoint with the header Authorization: Bearer <discord_webhook_secret>. Each message is run through sentiment analysis automatically.
Step 2 — Ingest Telemetry
POST player events to your ingest endpoint. Your studio_portal_key (spk_...) is the auth token. Include your game's game_id (from the studio portal) and the current build_tag:
POST /api/ingest Authorization: Bearer spk_... Content-Type: application/json { "game_id": "550e8400-e29b-41d4-a716-446655440000", "build_tag": "v2.4.1", "player_id": "player_abc123", "event_type": "session_start", "event_ts": "2026-05-29T09:00:00Z" }
NoteEvents are written to ClickHouse. The recommendation engine aggregates the last 7 days of events per build tag. Send events for every session start and key in-game milestone.
Step 3 — Read Your First Recommendation
Once enough telemetry has accumulated (24–48 hours), call the recommendations endpoint:
GET /api/games/{game_id}/recommendations/latest?build_tag=v2.4.1 X-Metriquality-Portal-Key: spk_...
{
"recommendation_type": "aggressive_uacq",
"confidence_score": 0.87,
"data_tier": "tier_2_telemetry",
"is_algorithmic_fallback": false,
"upgrade_prompt": null,
"confidence_degradation_reason": null,
"generated_at": "2026-06-06T09:00:00.000Z",
"rationale": "Rival Arena: Champions CCU down 38% in 48h. Your retention holding at 0.94. Acquisition window open.",
"execution_payload": {
"action_type": "increase_ad_spend",
"target_metric": "marketing_budget",
"suggested_value": 1.5,
"priority": "high"
},
"log_id": "a1b2c3d4-..."
}
is_algorithmic_fallback — true when the AI inference engine was unavailable and the recommendation came from deterministic rules. Outbound dispatch is suppressed for fallback recommendations — do not auto-execute them. Surface this flag in any automated integration so operators know the AI was offline.
data_tier — One of tier_0_no_data, tier_1_scraped_only, tier_2_telemetry, tier_3_velocity. Confidence scores are hard-capped at 0.40 for Tier 0/1. When upgrade_prompt is non-null the engine recommends integrating the telemetry SDK to unlock higher-confidence recommendations.
confidence_degradation_reason — Non-null when the studio crisis gate fired (own-game retention declining). The gate prevents aggressive_uacq during a retention crash and caps confidence. Surface this in your UI so operators understand why the score is lower than expected.
generated_at — ISO 8601 timestamp of when the recommendation was computed. Recommendations reflect the correlation snapshot at that instant. Re-call the endpoint every 15–30 minutes during active market windows; market conditions can shift faster than that during major competitor incidents.
Save the log_id. You'll use it to submit your outcome 7 days later so the engine can compute the measured impact (an internal before/after effect-size estimate; directional unless you ran a holdout).
Authentication
All studio-facing API endpoints require your studio portal key (spk_... prefix). Pass it in the X-Metriquality-Portal-Key header.
X-Metriquality-Portal-Key: spk_abc123...
Keys are tenant-scoped. Requests using a valid key for a different tenant return 403 Forbidden. Missing or invalid keys return 401 Unauthorized.
WarningTreat your portal key as a secret. It authorises data export and competitor watchlist mutations. Rotate it from your studio portal if compromised.
Studio Portal API
Returns the full dashboard payload: games list, latest recommendations per game, competitor vulnerability scores, and signal summaries.
Register a new game under your studio.
{ "title": "My Game", "genre": "Action", "platforms": ["Steam"] }
Remove a game from monitoring.
List your studio's competitor watchlist.
Add a rival to your watchlist. The poller will pick it up within ~30 minutes.
{ "steam_app_id": "730", "platform": "steam" }
Remove a rival from your watchlist.
Telemetry Ingestion
Ingest a player event. Events are written to ClickHouse and aggregated into velocity, retention, and CCU signals for the recommendation engine.
| Field | Type | Required | Description |
|---|---|---|---|
| game_id | UUID | Yes | Your game's ID from the studio portal |
| build_tag | string | Yes | Semver of current build — e.g. v2.4.1 |
| player_id | string | Yes | Stable anonymous player identifier |
| event_type | string | Yes | session_start | session_end | custom event name |
| event_ts | ISO 8601 | Yes | Client-side event timestamp |
| metadata | object | No | Arbitrary key-value pairs (max 10 keys) |
Noteplayer_id is used to compute distinct player counts (units) and CCU. It is hashed on receipt and never stored in plaintext. Do not send PII.
Recommendations
Returns the current recommendation for a game. Combines live telemetry, competitor signals, and market estimates. Responds in under 2 seconds; falls back to a deterministic matrix if inference times out.
Query parameters
| Param | Required | Description |
|---|---|---|
| build_tag | Yes | Current build semver — e.g. v2.4.1 |
| tenant_id | No | Inferred from portal key if omitted |
Recommendation types
| Type | Meaning |
|---|---|
| aggressive_uacq | Competitor distress + your retention holding → ramp user acquisition now |
| review_bomb_containment | Sentiment crisis + stable retention → pause feature rollout, monitor |
| change_freeze | External market chaos → lock releases, do not ship |
| no_action | No significant signal → continue monitoring |
Response headers
| Header | Description |
|---|---|
| X-Metriquality-Log-ID | UUID identifying this recommendation. Pass to outcome submission. |
| X-Metriquality-Recommendation-Stale | true if market context timed out — recommendation based on cached signals |
| X-Data-Status | ready | insufficient | stale |
Market Context
Returns estimated unit sales for your competitor watchlist alongside your own game's first-party actuals. Own-game data is sourced from your telemetry events — it is never an estimate.
{
"own_game": {
"game_id": "550e8400-...",
"title": "My Game",
"units": 84200,
"ccu_peak": 3100,
"is_estimate": false,
"data_source": "first_party_telemetry",
"confidence": "measured"
},
"competitor_estimates": [
{
"steam_app_id": "730",
"competitor_name": "Rival Arena: Champions",
"total_estimated_units": 420000,
"is_estimate": true,
"confidence": "medium",
"coverage_score": 0.74
}
]
}
NoteCompetitor estimates use the Boxleiter model calibrated against confirmed publisher-disclosed milestones. Steam-only. Console scrapers are running; console estimation is not yet available.
Outcomes
Submit metric deltas 7 days after executing a recommendation. Metriquality runs a before/after significance test automatically and returns a measured-impact estimate (lift evidence — directional unless you ran a holdout / geo-split).
{
"measured_retention_delta": 4.2, // percentage points
"measured_velocity_delta": null, // null if not measurable
"pre_retention": 0.88,
"cohort_size": 1200
}
The response includes p_value, confidence_level, and observed_effect ("lift" | "regress" | "neutral" | "insufficient_signal"). The p-value is an internal effect-size indicator, not proof of causation.
NoteYou don't have to submit outcomes manually. Metriquality's auto-outcome computer runs nightly and computes results automatically for completed recommendations with sufficient post-action data. Manual submission just gets you the result sooner.
Webhooks
All webhook endpoints are provisioned at signup. Secrets are per-tenant and rotatable from the studio portal.
| Endpoint | Auth header | Events captured |
|---|---|---|
| /api/jira/:tenant_id | X-Jira-Signature: sha256=... | Sprint open/close, issue resolved |
| /api/v1/webhooks/github/:tenant_id | X-Hub-Signature-256 | PR merged, issue closed |
| /api/discord/:tenant_id | Authorization: Bearer ... | Messages → sentiment analysis |
| /api/webhooks/crm/:tenant_id | X-Webhook-Secret or provider signature | Stripe, Shopify, HubSpot sales events |
NoteAll webhook endpoints are idempotent. Duplicate deliveries (same X-GitHub-Delivery or equivalent) are deduplicated and ignored.
Data Export
Exports your complete recommendation history, outcomes, playbook definitions, and raw signals in GS-CompInt-2026 format. Requires your spk_ portal key — cross-tenant requests return 403.
Responses carry the header X-GS-CompInt-Version: GS-CompInt-2026. The export is yours to keep — no Metriquality dependency required to read or validate it.
The Open Competitive Intelligence Standard
GS-CompInt-2026 is an open data standard for game studio competitive intelligence. It specifies a portable, vendor-neutral format for competitor incidents, studio outcomes, correlation signals, and playbook definitions.
Any tool that can read JSON can read a GS-CompInt-2026 export. You're not locked in to Metriquality's platform to use your own data.
Schema
A GS-CompInt-2026 document is a JSON object with four top-level fields:
{
"version": "GS-CompInt-2026",
"incidents": [ /* MarketIncident[] */ ],
"outcomes": [ /* RecommendationOutcome[] */ ],
"correlation": [ /* CorrelationSnapshot[] */ ],
"playbooks": [ /* PlaybookDefinition[] */ ]
}
MarketIncident
{
"competitor_game_id": "string (UUID)",
"competitor_build_tag": "string (semver)",
"incident_type": "patch_day | server_outage | content_drop | live_event | emergency_fix | api_breaking",
"source_ts": "ISO 8601"
}
RecommendationOutcome
{
"log_id": "string (UUID)",
"recommendation_type": "string",
"measured_retention_delta": "number | null",
"p_value": "number | null",
"confidence_level": "number | null",
"observed_effect": "lift | regress | neutral | insufficient_signal | null"
}
CorrelationSnapshot
{
"game_id": "string (UUID)",
"build_tag": "string (semver)",
"velocity_dau_pct": "number",
"retention_inverse": "number",
"sentiment_score": "number",
"queried_at": "ISO 8601"
}
Discovery Endpoint
Third-party tools can discover the current schema version without cloning this repo:
GET https://metriquality.se/.well-known/gs-compint-2026.json // Response header: X-GS-CompInt-Version: GS-CompInt-2026
Validator CLI
Validate any GS-CompInt-2026 document without a Metriquality account:
# Via npm npx gs-compint-validate path/to/export.json # Via Metriquality's built-in script npm run validate-outcome -- path/to/export.json
Exit codes
| Code | Meaning |
|---|---|
| 0 | Valid GS-CompInt-2026 document |
| 1 | Invalid — schema violations printed to stderr |
| 2 | Usage error — no file provided or file not found |
Open-Source Outcome Validator
The outcome validator runs a Welch's t-test on pre/post recommendation metric deltas to estimate whether an observed change is a measurable effect — or could plausibly be explained by random variance. This is an internal effect-size indicator, not proof of causation; a single-cohort before/after test is directional unless you ran a holdout / geo-split control.
The math is open. You can audit it, run it locally, or integrate it into your own data warehouse. No Metriquality account required.
Usage
npm run validate-outcome -- export.json # Or pipe a JSON document directly: cat export.json | npx gs-compint-validate
The validator reads outcomes[] from a GS-CompInt-2026 export and prints a verdict per outcome:
✓ log_id: a1b2c3... LIFT p=0.031 retention_delta=+4.2pts ~ log_id: d4e5f6... INSUFFICIENT_SIGNAL p=0.112 cohort below minimum ✗ log_id: g7h8i9... REGRESS p=0.008 delta in wrong direction
Statistical Model
Welch's t-test is used rather than Student's t-test because it does not assume equal variance between the pre-action and post-action populations. This is appropriate for game analytics where pre/post sample sizes and variance often differ.
Inputs
- pre_retention — baseline retention rate before the recommendation was executed
- measured_retention_delta — observed change in retention after 7 days
- cohort_size — number of players in the measurement window
Thresholds
| observed_effect | p-value | Minimum cohort |
|---|---|---|
| lift | < 0.05 (positive direction) | 30+ players |
| insufficient_signal | ≥ 0.05 | Any |
| regress | < 0.05 (wrong direction) | 30+ players |
Limitations — When Not to Use This Test
Warning — Correlation ≠ CausationThe t-test tells you whether the delta is statistically significant. It does not prove that the recommendation caused the change. Confounding variables (seasonal events, competitor news, platform updates) can produce significant p-values for reasons unrelated to your action.
- Cohort size < 30 — the test has insufficient power and results are unreliable. The validator will return
insufficient_signal. - Measurement window < 7 days — behavioural changes take time to manifest in retention metrics. Submit outcomes after the full window.
- Multiple simultaneous changes — if you shipped a patch and ran a UA campaign simultaneously, you cannot attribute the delta to either independently.
- Non-normal distributions — if your player base has extreme outlier behaviour (e.g. whales dominating session length), the t-test's normality assumptions may not hold. Check your distribution first.
- Velocity delta — DAU velocity is not computed by the retrospective validator because the pre-action baseline cannot be reliably reconstructed from retention-only data. This field is always stored as
null.
NoteThe validator follows the honesty gate principle: when data is insufficient, it skips the computation entirely rather than returning a zero or a confident-looking number. An empty result is always preferable to a fabricated one.