---
title: "Stats Advanced"
description: "Advanced analytics endpoints for the UTM hierarchy — mediums, sources, campaigns, terms — plus landing pages, channels, and microconversions"
canonical_url: "https://docs.sealmetrics.com/api/stats-advanced"
lang: "en"
date_generated: "2026-09-22T07:11:17.704Z"
source_hash: "34d5652a6fab079f4e5558f427e07006917b5f8cadddd5de766633ca5b58d80c"
content_type: "api-reference"
owner: "engineering"
llm_priority: "critical"
source_file: "api/stats-advanced.mdx"
publisher: "Sealmetrics"
---

# Stats Advanced

Canonical page: https://docs.sealmetrics.com/api/stats-advanced

Complete reference for advanced analytics endpoints including UTM hierarchy, landing pages, channels, and microconversions.

---

## UTM Hierarchy

Sealmetrics organizes traffic data in a hierarchical UTM structure:

```
Medium (email, organic, paid, referral)
  └── Source (google, facebook, newsletter)
       └── Campaign (spring_sale, brand_awareness)
            └── Term (running shoes, blue widget)
                 └── Content (banner_a, text_link)
```

Each level can be queried independently with filters from parent levels.

---

## Traffic by Medium

```http
GET /stats/mediums
```

Get traffic metrics grouped by UTM medium.

**Query Parameters:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `site_id` | string | required | Site ID (alias: `account_id`) |
| `period` | string | - | Date period (see [Periods](#date-periods)) |
| `start_date` | date | - | Custom start date (YYYY-MM-DD) |
| `end_date` | date | - | Custom end date (YYYY-MM-DD) |
| `segment` | string | - | Apply saved segment filters |
| `country` | string | - | Filter by country code (ISO 2-letter) |
| `filters` | string | - | Advanced filters (see [Filtering](./pagination-sorting#advanced-filters)) |
| `search` | string | - | Case-insensitive search on `utm_medium` (max 200 chars) |
| `sort_by` | string | `entrances` | Sort field (see [Sort Fields](#sort-fields)) |
| `sort_order` | string | `desc` | Sort order (`asc`/`desc`) |
| `page` | integer | `1` | Page number |
| `page_size` | integer | `50` | Items per page (1-100) |
| `compare` | string | - | Comparison mode (`previous`/`yoy`) — adds top-level `comparison` totals |
| `include_totals` | boolean | `false` | Add aggregated `totals` for the current period to the response |

**Response:**

```json
{
  "data": [
    {
      "utm_medium": "organic",
      "entrances": 15420,
      "engaged_entrances": 12336,
      "page_views": 45780,
      "conversions": 245,
      "revenue": 18650.00,
      "bounce_rate": 20.0
    },
    {
      "utm_medium": "paid",
      "entrances": 8750,
      "engaged_entrances": 6125,
      "page_views": 22400,
      "conversions": 180,
      "revenue": 14200.00,
      "bounce_rate": 30.0
    }
  ],
  "total": 5,
  "page": 1,
  "page_size": 50,
  "has_next": false,
  "has_prev": false
}
```

---

## Traffic by Source

```http
GET /stats/sources
```

Get traffic metrics grouped by UTM source. Same query params as [`/stats/mediums`](#traffic-by-medium), with one addition:

| Parameter | Type | Description |
|-----------|------|-------------|
| `utm_medium` | string | Filter by specific medium |

`search` matches on `utm_source` instead of `utm_medium`.

**Response:**

```json
{
  "data": [
    {
      "utm_source": "google",
      "entrances": 12500,
      "engaged_entrances": 10000,
      "page_views": 35000,
      "conversions": 150,
      "revenue": 12500.00,
      "bounce_rate": 20.0
    }
  ],
  "total": 25,
  "page": 1,
  "page_size": 50
}
```

### Top Sources

```http
GET /stats/sources/top
```

Get top sources by entrances.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `limit` | integer | `10` | Number of results (1-100) |
| `utm_medium` | string | - | Filter by medium |
| `country` | string | - | Filter by country (ISO 2-letter or `Unknown`) |
| `landing_page` | string | - | Only sessions that entered on this path (exact, case-insensitive; trailing slash counts) |

With `landing_page`, the endpoint returns the sources of the sessions that entered on that page, so the totals add up to that page's entrances. It reads the landing-page report, which has no pageview data, so **rows have no `page_views` key**; `utm_source`, `utm_medium`, `entrances`, `engaged_entrances`, `bounces`, `bounce_rate`, `microconversions`, `conversions`, `conversion_rate` and `revenue` are all present. Advanced `filters=` are not applied in this mode. Without `landing_page`, the response is unchanged.

---

## Traffic by Campaign

```http
GET /stats/campaigns
```

Get traffic metrics grouped by UTM campaign. Same query params as [`/stats/mediums`](#traffic-by-medium), with these additions:

| Parameter | Type | Description |
|-----------|------|-------------|
| `utm_medium` | string | Filter by medium |
| `utm_source` | string | Filter by source |

`search` matches on `utm_campaign`.

### Top Campaigns

```http
GET /stats/campaigns/top
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `limit` | integer | `10` | Number of results (1-100) |
| `utm_medium` / `utm_source` | string | - | UTM filters |
| `country` | string | - | Filter by country |

---

## Traffic by Term

```http
GET /stats/terms
```

Get traffic metrics grouped by UTM term (search keywords). Same query params as [`/stats/mediums`](#traffic-by-medium), with these additions:

| Parameter | Type | Description |
|-----------|------|-------------|
| `utm_medium` | string | Filter by medium |
| `utm_source` | string | Filter by source |
| `utm_campaign` | string | Filter by campaign |

`search` matches on `utm_term`.

### Top Terms

```http
GET /stats/terms/top
```

Same params as `/stats/campaigns/top`, accepts `utm_campaign` filter.

---

## Traffic by Content

```http
GET /stats/contents
```

Get traffic by UTM content parameter (ad variations, link types). Same query params as [`/stats/mediums`](#traffic-by-medium), with these additions:

| Parameter | Type | Description |
|-----------|------|-------------|
| `utm_medium` | string | Filter by medium |
| `utm_source` | string | Filter by source |
| `utm_campaign` | string | Filter by campaign |

`search` matches on `utm_content`.

### Top Contents

```http
GET /stats/contents/top
```

Same params as `/stats/campaigns/top`, accepts `utm_campaign` filter.

---

## Referrer Traffic

```http
GET /stats/referrers
```

Get traffic from external referrer domains.

**Response:**

```json
{
  "data": [
    {
      "referrer": "facebook.com",
      "entrances": 5420,
      "engaged_entrances": 3254,
      "page_views": 12500,
      "conversions": 45,
      "revenue": 3200.00,
      "bounce_rate": 40.0
    }
  ],
  "total": 150,
  "page": 1,
  "page_size": 50
}
```

### Top Referrers

```http
GET /stats/referrers/top
```

---

## Landing Pages

```http
GET /stats/landing-pages
```

Get metrics for entry pages (first page of session). Backed by `report_landing_pages`, which carries conversion and engagement data per entry page.

**Query Parameters:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `site_id` | string | required | Site identifier |
| `start_date` / `end_date` / `period` | date / string | - | Date range (see [Date Periods](#date-periods)) |
| `segment` | string | - | Apply saved segment (ID or name) |
| `content_grouping` | string | - | Filter by content group |
| `path_filter` | string | - | Filter by path (LIKE search) |
| `country` | string[] | - | Filter by country (ISO 2-letter, repeat for OR) |
| `utm_source` / `utm_medium` / `utm_campaign` / `utm_term` | string[] | - | Filter by UTM (repeat for OR) |
| `device_type` / `browser` / `os` | string[] | - | Filter by device dimension (repeat for OR) |
| `channel_group` | string[] | - | Filter by channel group. Use `""` for pre-migration rows |
| `include` | string[] | - | Add dimensions to GROUP BY and response. Allowed: `device`, `browser`, `os`, `channel_group` |
| `filters` | string | - | Advanced filters `field:op:value,...` (`eq`, `ne`, `contains`, `not_contains`, `regex`, `in`, `not_in`) |
| `sort_by` | string | `entrances` | `entrances`, `engaged_entrances`, `microconversions`, `conversions`, `revenue`, `bounce_rate` |
| `sort_order` | string | `desc` | `asc` or `desc` |
| `page` | integer | `1` | Page number |
| `page_size` | integer | `50` | Items per page (1-1000) |
| `compare` | string | - | `previous` or `yoy` — adds `comparison` totals + per-row `_prev` fields |
| `include_totals` | boolean | `false` | Add aggregated `totals` for the current period to the response |
| `include_utm` | boolean | `false` | Group by UTM and include `utm_*` fields in each row |

Unknown `include` values return **422 Unprocessable Entity**.

**Response:**

```json
{
  "data": [
    {
      "landing_page": "/products/running-shoes",
      "content_grouping": "Products",
      "entrances": 8500,
      "engaged_entrances": 6800,
      "bounce_rate": 20.0,
      "microconversions": 1200,
      "conversions": 85,
      "conversion_rate": 1.0,
      "revenue": 7650.00
    }
  ],
  "total": 450,
  "page": 1,
  "page_size": 50,
  "has_next": true,
  "has_prev": false
}
```

When `include_utm=true`, each row also includes `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content`. When `include` is set, each row carries the requested dimension column(s). When `compare` is set, the response includes a top-level `comparison` object with previous-period totals and each row gets `_prev` metric fields. When `include_totals=true`, the response includes a `totals` object aggregating the current period.

### Top Landing Pages

```http
GET /stats/landing-pages/top
```

Top landing pages by entrances. Returns the same metric shape as `/stats/landing-pages` rows.

**Query Parameters:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `site_id` | string | required | Site identifier |
| `start_date` / `end_date` / `period` | date / string | - | Date range |
| `utm_source` / `utm_medium` | string | - | UTM filters (single value). `utm_campaign` and `utm_term` are **not** accepted on this endpoint — use `/stats/landing-pages` if you need to filter by them |
| `country` | string | - | Filter by country |
| `content_grouping` | string | - | Filter by content group |
| `filters` | string | - | Advanced filters `field:op:value,...` |
| `limit` | integer | `10` | Number of results (1-100) |

**Response:**

```json
{
  "data": [
    {
      "landing_page": "/products/running-shoes",
      "content_grouping": "Products",
      "entrances": 8500,
      "engaged_entrances": 6800,
      "bounce_rate": 20.0,
      "microconversions": 1200,
      "conversions": 85,
      "conversion_rate": 1.0,
      "revenue": 7650.00
    }
  ]
}
```

### Landing Pages by Content Group

```http
GET /stats/landing-pages/by-content-group
```

Aggregate landing page metrics by content group. Returns one row per group with `unique_pages` count and the full engagement/conversion metric set.

**Query Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `site_id` | string | required |
| `start_date` / `end_date` / `period` | date / string | Date range |
| `utm_source` / `utm_medium` | string | UTM filters (single value) |
| `country` | string | Filter by country |

**Response:**

```json
{
  "data": [
    {
      "content_grouping": "Products",
      "unique_pages": 56,
      "entrances": 24500,
      "engaged_entrances": 19200,
      "bounce_rate": 21.6,
      "microconversions": 3400,
      "conversions": 245,
      "conversion_rate": 1.0,
      "revenue": 21500.00
    }
  ]
}
```

---

## Channel Groups

```http
GET /stats/channels
```

Get traffic by GA4-style channel grouping.

Sealmetrics automatically classifies traffic into channels based on UTM parameters:

| Channel | Classification |
|---------|---------------|
| Direct | No referrer, no UTM |
| Organic Search | `medium=organic`, source is search engine |
| Paid Search | `medium=cpc\|ppc\|paid` |
| Display | `medium=display\|banner` |
| Email | `medium=email` |
| Social | Source is social network |
| Referral | Has referrer, no UTM |
| Affiliate | `medium=affiliate` |

**Query Parameters:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `site_id` | string | required | Site ID (alias: `account_id`) |
| `start_date` / `end_date` / `period` | date / string | - | Date range |
| `segment` | string | - | Apply saved segment |
| `country` | string | - | Filter by country (ISO 2-letter) |
| `filters` | string | - | Advanced filters |
| `search` | string | - | Case-insensitive search on channel name (max 200 chars) |
| `sort_by` | string | `entrances` | `entrances`, `engaged_entrances`, `page_views`, `conversions`, `revenue` |
| `sort_order` | string | `desc` | `asc` or `desc` |
| `page` | integer | `1` | Page number |
| `page_size` | integer | `50` | Items per page (1-100) |
| `compare` | string | - | `previous` or `yoy` — adds row-level `_prev` fields and top-level `comparison` |
| `include_totals` | boolean | `false` | Include aggregated totals for the current period |

**Response:**

```json
{
  "data": [
    {
      "channel": "Organic Search",
      "entrances": 25000,
      "engaged_entrances": 20000,
      "page_views": 75000,
      "microconversions": 3400,
      "conversions": 350,
      "revenue": 28000.00,
      "bounce_rate": 20.0
    }
  ],
  "total": 8,
  "page": 1,
  "page_size": 50,
  "has_next": false,
  "has_prev": false
}
```

### Top Channels

```http
GET /stats/top-channels
```

Top channels by entrances.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `site_id` | string | required | Site ID |
| `start_date` / `end_date` / `period` | date / string | - | Date range |
| `country` | string | - | Filter by country |
| `limit` | integer | `10` | Number of results (1-50) |

**Response:** `APIResponse<Channel[]>` with the same metric shape as `/stats/channels` rows.

---

## Microconversions

Microconversions track intermediate user actions (add to cart, form start, video play, etc.).

### List Microconversions

```http
GET /stats/microconversions
```

**Query Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `utm_source` | string | Filter by source |
| `utm_medium` | string | Filter by medium |
| `utm_campaign` | string | Filter by campaign |
| `utm_term` | string | Filter by term |
| `country` | string | Filter by country (ISO 2-letter) |
| `device_type` | string | Filter by device (`desktop`/`mobile`/`tablet`) |
| `browser` | string | Filter by browser |
| `os` | string | Filter by operating system |
| `conversion_type` | string | Filter by specific type |
| `segment` | string | Apply saved segment |
| `filters` | string | Advanced filters |
| `sort_by` | string | Sort by: `count` |
| `compare` | string | Comparison mode |

**Response:**

```json
{
  "data": [
    {
      "conversion_type": "add_to_cart",
      "count": 4520,
      "utm_source": "google",
      "utm_medium": "cpc",
      "utm_campaign": "spring_sale"
    },
    {
      "conversion_type": "newsletter_signup",
      "count": 890,
      "utm_source": "facebook",
      "utm_medium": "social",
      "utm_campaign": null
    }
  ],
  "total": 125,
  "page": 1,
  "page_size": 20
}
```

---

### Microconversion Details

```http
GET /stats/microconversions/{conversion_type}
```

Get detailed breakdown for a specific microconversion type.

**Path Parameters:**

| Parameter | Description |
|-----------|-------------|
| `conversion_type` | Type of microconversion (e.g., `add_to_cart`) |

**Response:**

```json
{
  "success": true,
  "data": {
    "conversion_type": "add_to_cart",
    "total_count": 4520,
    "by_source": [
      {"utm_source": "google", "count": 2500},
      {"utm_source": "facebook", "count": 1200}
    ],
    "by_country": [
      {"country": "ES", "count": 2800},
      {"country": "FR", "count": 950}
    ],
    "by_device": [
      {"device_type": "mobile", "count": 2700},
      {"device_type": "desktop", "count": 1820}
    ],
    "by_landing_page": [
      {"path": "/products/shoes", "count": 1500},
      {"path": "/sale", "count": 980}
    ]
  }
}
```

---

### Available Microconversion Types

```http
GET /stats/microconversions-types
```

Get list of microconversion types with data in the selected period.

**Response:**

```json
{
  "success": true,
  "data": [
    "add_to_cart",
    "newsletter_signup",
    "video_play",
    "form_start",
    "wishlist_add"
  ]
}
```

---

## Date Periods

All stats endpoints accept a `period` parameter with these values:

### Relative Periods

| Value | Description |
|-------|-------------|
| `today` | Current day (midnight to now) |
| `yesterday` | Previous complete day |
| `7d` | Last 7 days including today |
| `30d` | Last 30 days including today |
| `90d` | Last 90 days including today |
| `12m` | Last 12 months (365 days) |

### Calendar Periods

| Value | Description |
|-------|-------------|
| `this_week` | Current week (Monday to today) |
| `last_week` | Previous complete week (Mon-Sun) |
| `this_month` | Current month (1st to today) |
| `last_month` | Previous complete month |
| `this_quarter` | Current quarter to today |
| `last_quarter` | Previous complete quarter |
| `this_year` | January 1st to today |
| `last_year` | Previous complete year |

### To-Date Aliases

| Value | Equivalent |
|-------|------------|
| `wtd` | `this_week` |
| `mtd` | `this_month` |
| `qtd` | `this_quarter` |
| `ytd` | `this_year` |

### How "today" is resolved

Every preset is resolved with **"today" in the account's timezone** (`accounts.timezone`), not in UTC or in the caller's browser. This matches how the data is stored — the pixel-service pre-computes each hit's local `date` using the account's timezone — and mirrors what GA4, Plausible and Matomo call the "reporting timezone".

Consequences worth knowing:

- Two accounts in different timezones will see different windows for `today` even at the exact same wall-clock instant.
- Explicit `start_date` / `end_date` (ISO `YYYY-MM-DD`) are also interpreted as **local days in the account's timezone**.
- The stats and query endpoints (`/stats/*`, `/stats/query`, `/batch`, `/channel-groups/stats/*`) all follow this rule. If you write your own tooling that pre-resolves a range client-side, use the account's timezone as your reference — don't use the server's UTC clock.
- Changing a site's timezone in Settings takes effect on the API within ~5 min (the timezone cache TTL).

### Period comparison

Set `compare=previous` (or `yoy` where supported) on any endpoint that accepts `period` to also fetch the equivalent prior window. See each endpoint's response shape for how comparison fields are laid out.

---

## Sort Fields

Different endpoints support different sort fields:

### Traffic Endpoints

`/stats/sources`, `/stats/campaigns`, `/stats/mediums`, etc.

| Field | Description |
|-------|-------------|
| `entrances` | Session starts (default) |
| `engaged_entrances` | Engaged sessions |
| `page_views` | Total page views |
| `conversions` | Total conversions |
| `revenue` | Total revenue |

### Conversion Endpoints

`/stats/conversions`

| Field | Description |
|-------|-------------|
| `count` | Number of conversions (default) |
| `revenue` | Total revenue |
| `avg_value` | Average conversion value |

### Microconversion Endpoints

`/stats/microconversions`

| Field | Description |
|-------|-------------|
| `count` | Number of microconversions (default) |

---

## Code Examples

### Get Top Sources by Revenue

```python
import requests

response = requests.get(
    "https://my.sealmetrics.com/api/v1/stats/sources",
    headers={"X-API-Key": "sm_your_api_key"},
    params={
        "site_id": "my-site",
        "period": "30d",
        "sort_by": "revenue",
        "sort_order": "desc",
        "page_size": 10
    }
)

for source in response.json()["data"]:
    print(f"{source['utm_source']}: €{source['revenue']}")
```

### Filter by Segment and Country

```python
response = requests.get(
    "https://my.sealmetrics.com/api/v1/stats/campaigns",
    headers={"X-API-Key": "sm_your_api_key"},
    params={
        "site_id": "my-site",
        "period": "7d",
        "segment": "paid-traffic",
        "country": "ES",
        "compare": "previous"
    }
)
```

### Get Microconversion Funnel

```python
# Get add_to_cart by source
carts = requests.get(
    "https://my.sealmetrics.com/api/v1/stats/microconversions",
    headers={"X-API-Key": "sm_your_api_key"},
    params={
        "site_id": "my-site",
        "period": "30d",
        "conversion_type": "add_to_cart"
    }
).json()

for item in carts["data"]:
    print(f"{item['utm_source']}: {item['count']} carts")
```
