# dev.cartridge.analytics.getGameAnalytics

> Published by [cartridge.dev](https://lexicon.garden/identity/did:plc:4mrwcmxk266itsdn33leqljq)

## Links

- [View on Lexicon Garden](https://lexicon.garden/lexicon/did:plc:4mrwcmxk266itsdn33leqljq/dev.cartridge.analytics.getGameAnalytics)
- [Documentation](https://lexicon.garden/lexicon/did:plc:4mrwcmxk266itsdn33leqljq/dev.cartridge.analytics.getGameAnalytics/docs)
- [Examples](https://lexicon.garden/lexicon/did:plc:4mrwcmxk266itsdn33leqljq/dev.cartridge.analytics.getGameAnalytics/examples)

## Definitions

### `dev.cartridge.analytics.getGameAnalytics`

**Type**: `query`

Owner-facing analytics for a single game. Authenticates the caller, verifies they own the game, then merges ClickHouse rollups with record-creation trends from HappyView. Fractional metrics use `unknown` because atproto lexicons have no float type.

#### Parameters

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `slug` | `string` | Yes | Slug of the game to report on. The caller must own it. |
| `range` | `string` | No | Reporting window ending today (UTC). |

#### Output

**Encoding**: `application/json`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `name` | `string` | Yes |  |
| `slug` | `string` | Yes |  |
| `range` | `string` | Yes |  |
| `totals` | `ref` → `#totals` | Yes |  |
| `discovery` | `ref` → `#discovery` | Yes |  |
| `engagement` | `ref` → `#engagement` | Yes |  |
| `attribution` | `ref` → `#attribution` | Yes |  |
| `conversions` | `ref` → `#conversions` | Yes |  |
| `generatedAt` | `string` (datetime) | Yes |  |

### `dev.cartridge.analytics.getGameAnalytics#funnel`

**Type**: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `actions` | `integer` | Yes |  |
| `pageviews` | `integer` | Yes |  |
| `impressions` | `integer` | Yes |  |

### `dev.cartridge.analytics.getGameAnalytics#totals`

**Type**: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `ctr` | `unknown` | Yes | clicks / impressions, 0..1 (float; unknown-typed). |
| `clicks` | `integer` | Yes |  |
| `pageviews` | `integer` | Yes |  |
| `avgDwellMs` | `unknown` | Yes | Mean dwell time in milliseconds (float; unknown-typed). |
| `impressions` | `integer` | Yes |  |
| `avgScrollPct` | `unknown` | Yes | Mean scroll depth percentage (float; unknown-typed). |
| `medianDwellMs` | `unknown` | Yes | Median dwell time in milliseconds (float; unknown-typed). |
| `avgDailyUniques` | `unknown` | Yes | Mean of per-day unique visitors across the range (float; unknown-typed). |

### `dev.cartridge.analytics.getGameAnalytics#discovery`

**Type**: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `feedBreakdown` | `array` | Yes |  |
| `topSearchTerms` | `array` | Yes |  |
| `impressionsOverTime` | `array` | Yes |  |

### `dev.cartridge.analytics.getGameAnalytics#engagement`

**Type**: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `avgScrollPct` | `unknown` | Yes | Mean scroll depth percentage (float; unknown-typed). |
| `dailyUniques` | `array` | Yes |  |
| `tabEngagement` | `array` | Yes |  |
| `dwellDistribution` | `array` | Yes |  |

### `dev.cartridge.analytics.getGameAnalytics#namedCount`

**Type**: `object`

A labelled count, e.g. a feed name or search term with its total.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `name` | `string` | Yes |  |
| `count` | `integer` | Yes |  |

### `dev.cartridge.analytics.getGameAnalytics#attribution`

**Type**: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `ctrBySurface` | `array` | Yes |  |
| `trafficSources` | `array` | Yes |  |
| `topReferrerFeeds` | `array` | Yes |  |

### `dev.cartridge.analytics.getGameAnalytics#conversions`

**Type**: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `funnel` | `ref` → `#funnel` | Yes |  |
| `recordTrends` | `array` | Yes |  |

### `dev.cartridge.analytics.getGameAnalytics#ctrBySurface`

**Type**: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `ctr` | `unknown` | Yes | clicks / impressions for this surface, 0..1 (float; unknown-typed). |
| `clicks` | `integer` | Yes |  |
| `surface` | `string` | Yes |  |
| `impressions` | `integer` | Yes |  |

### `dev.cartridge.analytics.getGameAnalytics#impressionPoint`

**Type**: `object`

Impressions on one day, split by discovery surface.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `date` | `string` | Yes |  |
| `feed` | `integer` | Yes |  |
| `search` | `integer` | Yes |  |

### `dev.cartridge.analytics.getGameAnalytics#timeseriesPoint`

**Type**: `object`

A single day's value in a time series. `date` is 'YYYY-MM-DD' (UTC).

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `date` | `string` | Yes |  |
| `value` | `integer` | Yes |  |

### `dev.cartridge.analytics.getGameAnalytics#recordTrendPoint`

**Type**: `object`

Authoritative record-creation counts for one day.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `date` | `string` | Yes |  |
| `likes` | `integer` | Yes |  |
| `reviews` | `integer` | Yes |  |
| `listAdds` | `integer` | Yes |  |

## Raw Schema

```json
{
  "id": "dev.cartridge.analytics.getGameAnalytics",
  "defs": {
    "main": {
      "type": "query",
      "output": {
        "schema": {
          "type": "object",
          "required": [
            "slug",
            "name",
            "range",
            "generatedAt",
            "totals",
            "discovery",
            "attribution",
            "engagement",
            "conversions"
          ],
          "properties": {
            "name": {
              "type": "string"
            },
            "slug": {
              "type": "string"
            },
            "range": {
              "type": "string",
              "knownValues": [
                "7d",
                "30d",
                "90d"
              ]
            },
            "totals": {
              "ref": "#totals",
              "type": "ref"
            },
            "discovery": {
              "ref": "#discovery",
              "type": "ref"
            },
            "engagement": {
              "ref": "#engagement",
              "type": "ref"
            },
            "attribution": {
              "ref": "#attribution",
              "type": "ref"
            },
            "conversions": {
              "ref": "#conversions",
              "type": "ref"
            },
            "generatedAt": {
              "type": "string",
              "format": "datetime"
            }
          }
        },
        "encoding": "application/json"
      },
      "parameters": {
        "type": "params",
        "required": [
          "slug"
        ],
        "properties": {
          "slug": {
            "type": "string",
            "maxLength": 512,
            "description": "Slug of the game to report on. The caller must own it."
          },
          "range": {
            "type": "string",
            "default": "30d",
            "description": "Reporting window ending today (UTC).",
            "knownValues": [
              "7d",
              "30d",
              "90d"
            ]
          }
        }
      },
      "description": "Owner-facing analytics for a single game. Authenticates the caller, verifies they own the game, then merges ClickHouse rollups with record-creation trends from HappyView. Fractional metrics use `unknown` because atproto lexicons have no float type."
    },
    "funnel": {
      "type": "object",
      "required": [
        "impressions",
        "pageviews",
        "actions"
      ],
      "properties": {
        "actions": {
          "type": "integer"
        },
        "pageviews": {
          "type": "integer"
        },
        "impressions": {
          "type": "integer"
        }
      }
    },
    "totals": {
      "type": "object",
      "required": [
        "impressions",
        "clicks",
        "pageviews",
        "ctr",
        "avgDwellMs",
        "medianDwellMs",
        "avgScrollPct",
        "avgDailyUniques"
      ],
      "properties": {
        "ctr": {
          "type": "unknown",
          "description": "clicks / impressions, 0..1 (float; unknown-typed)."
        },
        "clicks": {
          "type": "integer"
        },
        "pageviews": {
          "type": "integer"
        },
        "avgDwellMs": {
          "type": "unknown",
          "description": "Mean dwell time in milliseconds (float; unknown-typed)."
        },
        "impressions": {
          "type": "integer"
        },
        "avgScrollPct": {
          "type": "unknown",
          "description": "Mean scroll depth percentage (float; unknown-typed)."
        },
        "medianDwellMs": {
          "type": "unknown",
          "description": "Median dwell time in milliseconds (float; unknown-typed)."
        },
        "avgDailyUniques": {
          "type": "unknown",
          "description": "Mean of per-day unique visitors across the range (float; unknown-typed)."
        }
      }
    },
    "discovery": {
      "type": "object",
      "required": [
        "impressionsOverTime",
        "feedBreakdown",
        "topSearchTerms"
      ],
      "properties": {
        "feedBreakdown": {
          "type": "array",
          "items": {
            "ref": "#namedCount",
            "type": "ref"
          }
        },
        "topSearchTerms": {
          "type": "array",
          "items": {
            "ref": "#namedCount",
            "type": "ref"
          }
        },
        "impressionsOverTime": {
          "type": "array",
          "items": {
            "ref": "#impressionPoint",
            "type": "ref"
          }
        }
      }
    },
    "engagement": {
      "type": "object",
      "required": [
        "dwellDistribution",
        "avgScrollPct",
        "tabEngagement",
        "dailyUniques"
      ],
      "properties": {
        "avgScrollPct": {
          "type": "unknown",
          "description": "Mean scroll depth percentage (float; unknown-typed)."
        },
        "dailyUniques": {
          "type": "array",
          "items": {
            "ref": "#timeseriesPoint",
            "type": "ref"
          }
        },
        "tabEngagement": {
          "type": "array",
          "items": {
            "ref": "#namedCount",
            "type": "ref"
          }
        },
        "dwellDistribution": {
          "type": "array",
          "items": {
            "ref": "#namedCount",
            "type": "ref"
          }
        }
      }
    },
    "namedCount": {
      "type": "object",
      "required": [
        "name",
        "count"
      ],
      "properties": {
        "name": {
          "type": "string"
        },
        "count": {
          "type": "integer"
        }
      },
      "description": "A labelled count, e.g. a feed name or search term with its total."
    },
    "attribution": {
      "type": "object",
      "required": [
        "trafficSources",
        "topReferrerFeeds",
        "ctrBySurface"
      ],
      "properties": {
        "ctrBySurface": {
          "type": "array",
          "items": {
            "ref": "#ctrBySurface",
            "type": "ref"
          }
        },
        "trafficSources": {
          "type": "array",
          "items": {
            "ref": "#namedCount",
            "type": "ref"
          }
        },
        "topReferrerFeeds": {
          "type": "array",
          "items": {
            "ref": "#namedCount",
            "type": "ref"
          }
        }
      }
    },
    "conversions": {
      "type": "object",
      "required": [
        "recordTrends",
        "funnel"
      ],
      "properties": {
        "funnel": {
          "ref": "#funnel",
          "type": "ref"
        },
        "recordTrends": {
          "type": "array",
          "items": {
            "ref": "#recordTrendPoint",
            "type": "ref"
          }
        }
      }
    },
    "ctrBySurface": {
      "type": "object",
      "required": [
        "surface",
        "impressions",
        "clicks",
        "ctr"
      ],
      "properties": {
        "ctr": {
          "type": "unknown",
          "description": "clicks / impressions for this surface, 0..1 (float; unknown-typed)."
        },
        "clicks": {
          "type": "integer"
        },
        "surface": {
          "type": "string"
        },
        "impressions": {
          "type": "integer"
        }
      }
    },
    "impressionPoint": {
      "type": "object",
      "required": [
        "date",
        "search",
        "feed"
      ],
      "properties": {
        "date": {
          "type": "string"
        },
        "feed": {
          "type": "integer"
        },
        "search": {
          "type": "integer"
        }
      },
      "description": "Impressions on one day, split by discovery surface."
    },
    "timeseriesPoint": {
      "type": "object",
      "required": [
        "date",
        "value"
      ],
      "properties": {
        "date": {
          "type": "string"
        },
        "value": {
          "type": "integer"
        }
      },
      "description": "A single day's value in a time series. `date` is 'YYYY-MM-DD' (UTC)."
    },
    "recordTrendPoint": {
      "type": "object",
      "required": [
        "date",
        "likes",
        "reviews",
        "listAdds"
      ],
      "properties": {
        "date": {
          "type": "string"
        },
        "likes": {
          "type": "integer"
        },
        "reviews": {
          "type": "integer"
        },
        "listAdds": {
          "type": "integer"
        }
      },
      "description": "Authoritative record-creation counts for one day."
    }
  },
  "$type": "com.atproto.lexicon.schema",
  "lexicon": 1
}
```
