> For the complete documentation index, see [llms.txt](https://helps.ptengine.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://helps.ptengine.com/en/developer/open-api.md).

# Open API Documentation

***

## 1. General Conventions

### 1.1 Overview

The Ptengine Open API provides RESTful endpoints for programmatic access to heatmap and analytics data. You can hand this document to an AI Agent — the agent reads natural-language requests, builds the right query, and calls the API directly.

**Base URL:**

```
https://xbackend.ptengine.com/
```

### 1.2 Authentication

All requests must include the `x-api-key` header with your API Key.

```
x-api-key: pt-your-api-key-here
```

**How to get an API Key:**

> **Permission:** Only Admin and Owner roles can create and manage API Keys.

1. Log in to Ptengine
2. Open the Experience module
3. Click the settings icon (⚙) in the top-right and choose "External App Integration"
4. Switch to the "API Keys" tab
5. Click "Create API Key", enter a name and choose the permission scope (data upload / data query)
6. Copy and store the key safely (it is shown only once)

### 1.3 Rate Limits

Limits vary by plan:

| Plan       | RPM (per minute) | RPD (per day) |
| ---------- | ---------------- | ------------- |
| Free       | 3                | 100           |
| Free Trial | 10               | 1,000         |
| Growth     | 30               | 3,000         |

Rate-limit info is returned via response headers:

```
X-RateLimit-Limit-Minute: 30
X-RateLimit-Remaining-Minute: 28
X-RateLimit-Limit-Day: 3000
X-RateLimit-Remaining-Day: 2997
X-RateLimit-Tier: GROWTH
```

### 1.4 Response Format

All endpoints return JSON in a uniform wrapper:

* Success (HTTP 200): `{ "code": 200, "message": "OK", "data": ... }`
* Failure (HTTP 4xx): `{ "code": 4xxx, "message": "..." }`

A failure response may carry an additional `hint` field. When the metric or dimension name you passed is valid on **another endpoint**, `hint` names the field to use instead, or the endpoint the field belongs to:

```json
{
    "code": 4018,
    "message": "Invalid metric \"fvRate\"",
    "hint": "'fvRate' is not available on /open-api/v1/datacenter/query; it belongs to /open-api/v1/heatmap/query."
}
```

`hint` is optional and appears only when concrete guidance is available. It does not affect `code` or `message`.

See [Appendix — Error Codes](#error-codes) for the full list.

***

## 2. Insight

This chapter covers four query endpoints: Heatmap, Event, Data Center, and Conversion.

### 2.1 Common Rules

All four endpoints can be filtered by a conversion goal and all support `filters`. Where to look up conversion goal names; how to write `filters` and where to find the values inside them — all covered here.

**The field name differs per endpoint**; passing the wrong one returns 4018:

| Endpoint    | Field                                                                                     | Shape                                                       |
| ----------- | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| Heatmap     | `conversionNames`                                                                         | Array of strings, multiple goals allowed                    |
| Data Center | `conversionName`                                                                          | String, **a single goal only**                              |
| Conversion  | `conversionName`                                                                          | String, **a single goal only** (required for `funnel` only) |
| Event       | Inside `filters`: `{ "name": "conversionName", "op": "include", "value": ["Goal name"] }` | A filter condition, no top-level field                      |

#### Metric sets (`metricSet`)

Some metric names exist on more than one endpoint (`visits`, `bounceRate`, `newVisitsRate`), but their definitions differ and the values are not interchangeable. The `metricSet` field declares which set a response belongs to:

| `metricSet`                 | Endpoint    | Query type                      | Field location   |
| --------------------------- | ----------- | ------------------------------- | ---------------- |
| `datacenter.overview`       | Data Center | `overview`                      | `data.metricSet` |
| `datacenter.dimensionTable` | Data Center | `dimension_table`               | `data.metricSet` |
| `heatmap.page`              | Heatmap     | `page_metrics` / `page_insight` | `meta.metricSet` |
| `heatmap.block`             | Heatmap     | `block_metrics`                 | `meta.metricSet` |
| `heatmap.element`           | Heatmap     | `element_metrics`               | `meta.metricSet` |

**Metric availability by endpoint**

| Metric                        | Data Center `overview` | Data Center page table | Heatmap page                     |
| ----------------------------- | ---------------------- | ---------------------- | -------------------------------- |
| Visits                        | `visits`               | `visits`               | `visits`                         |
| Page views (PV)               | `pageView`             | `pageView`             | `pageView`                       |
| Unique visitors (UV)          | `users`                | —                      | `users`                          |
| New-visit rate                | `newVisitsRate`        | `newVisitsRate`        | `newVisitsRate`                  |
| Return-visit rate             | `returnVisitsRate`     | —                      | —                                |
| Page views per visitor        | `avgPageView`          | —                      | `avgPageView`                    |
| Visits per visitor            | `avgVisits`            | —                      | —                                |
| Avg visit duration            | `avgVisitDuration`     | —                      | —                                |
| Avg time on page              | —                      | `avgTimeOnPage`        | `avgTimeOnPage`                  |
| Avg page load time            | `avgLoadTime`          | —                      | —                                |
| Bounce rate                   | `bounceRate`           | `bounceRate`           | `bounceRate`                     |
| Exit rate                     | —                      | `exitRate`             | —                                |
| Entrances                     | —                      | `entrances`            | `entrances`                      |
| Clicks                        | —                      | `clicks`               | `clicks`                         |
| Click rate                    | —                      | —                      | `clickRate`                      |
| CTA clicks / click rate       | —                      | —                      | `ctaClicks` / `ctaClickRate`     |
| First-screen exit rate        | —                      | —                      | `fvRate`                         |
| Conversions / conversion rate | —                      | —                      | `conversions` / `conversionRate` |

A concept uses the same field name on every endpoint, so no alias mapping is needed. A `—` means the endpoint does not provide that metric.

> The Heatmap endpoint and Conversion `metric_curve` used a different set of field names in the past. They are now unified as shown above; the previous names are no longer accepted.

**Concept name (`canonical`)**

Most metrics carry a `canonical` field naming the underlying concept, so you can read values by concept without checking whether a given field has it. Its main use is separating concepts with similar names but different definitions:

```json
"avgVisitDuration": { "label": "Avg. visit duration", "canonical": "visitDuration", ... }
"avgTimeOnPage":    { "label": "Avg. time on page",   "canonical": "timeOnPage",    ... }
```

The first is the duration of an entire visit, the second is time spent on a single page. The values differ substantially and are not interchangeable.

#### Conversion Goals

When querying conversion data (e.g. "how many purchases completed", "what's the signup conversion rate"), you need to tell the system which conversion goal to query. This endpoint returns all goal names configured in Ptengine — copy a name into your query request.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/conversion/goals \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "conversions": [
            { "id": "1753350579776", "name": "ptmind signup" },
            { "id": "1753350579999", "name": "Purchase complete" }
        ]
    }
}
```

After getting `name`, pass it using the field name for that endpoint from the table above — e.g. Heatmap `"conversionNames": ["Purchase complete"]`, Data Center `"conversionName": "Purchase complete"`.

#### Filter

Add conditions to the `filters` field of your request body to narrow the data scope. For example: Mobile only, Japan only, a specific campaign source only.

```json
{ "name": "country", "op": "include", "value": ["Japan"] }
```

Fields:

| Field   | Meaning                                                           |
| ------- | ----------------------------------------------------------------- |
| `name`  | The field to filter on (see the categories below)                 |
| `op`    | `include` or `exclude`; no other operators                        |
| `value` | The value(s), must be an array (even a single value: `["Japan"]`) |

> Custom-property filters (filter by event property) need extra `eventName` / `eventVariant` fields — see "Custom-property filter (advanced)" below.

Fields fall into two categories:

**Fixed-value fields**

The four fields below accept fixed enumerated values — copy them verbatim:

| name         | Meaning     | Allowed values                                                   |
| ------------ | ----------- | ---------------------------------------------------------------- |
| `deviceType` | Device Type | `PC`, `Mobile`, `Tablet`                                         |
| `sourceType` | Source Type | `Direct`, `Search`, `Social`, `Referral`, `Campaign`, `AISearch` |
| `visitType`  | Visit Type  | `New visits`, `Returning visits`                                 |
| `exitType`   | Exit Type   | `Bounce visits`, `Non-bounce visits`                             |

**Dynamic-value fields**

Values vary by data. Query them via the [filter-values](#filter-values) endpoint below.

| Category   | name               | Meaning                        | value example                                                |
| ---------- | ------------------ | ------------------------------ | ------------------------------------------------------------ |
| Device     | `os`               | Operating system               | `["Windows", "Mac OS X"]`                                    |
| Device     | `osVersion`        | OS version                     | `["Windows 10", "Mac OS X 10.15.7", "iOS 17.0"]`             |
| Device     | `browser`          | Browser                        | `["Chrome", "Mobile Safari", "Edge"]`                        |
| Device     | `browserVersion`   | Browser version                | `["Chrome 124.0.0", "Edge 146.0.0", "Mobile Safari 13.0.3"]` |
| Device     | `screenResolution` | Screen resolution              | `["1920x1080", "1440x900"]`                                  |
| Device     | `deviceBrand`      | Device brand                   | `["Apple", "Samsung"]`                                       |
| Geo        | `country`          | Country / Area                 | `["Japan", "China", "United States"]`                        |
| Geo        | `region`           | State / Region                 | `["Tokyo", "Beijing", "Hong Kong"]`                          |
| Source     | `searchEngine`     | Search engine                  | `["google"]`                                                 |
| Source     | `socialNetwork`    | Social network                 | `["facebook"]`                                               |
| Source     | `socialUrl`        | Social URL                     | `["https://www.facebook.com/"]`                              |
| Source     | `aiName`           | AI search                      | `["ChatGPT", "Perplexity"]`                                  |
| Source     | `referralSource`   | Referral website               | `["www.muji.com"]`                                           |
| Source     | `referralUrl`      | Referral URL                   | `["https://www.muji.com/"]`                                  |
| Ad         | `campaignUrl`      | Campaign URL                   | `["https://www.google.com/"]`                                |
| Ad         | `utmCampaign`      | Campaign name                  | `["summer_sale"]`                                            |
| Ad         | `utmSource`        | Source (UTM)                   | `["google", "facebook"]`                                     |
| Ad         | `utmMedium`        | Medium (UTM)                   | `["cpc", "email"]`                                           |
| Ad         | `utmTerm`          | Term (UTM)                     | `["heatmap tool"]`                                           |
| Ad         | `utmContent`       | Content (UTM)                  | `["banner_a"]`                                               |
| Page       | `combinedPages`    | Entry page (combined)          | `["https://ptengine.jp/app/login"]`                          |
| Page       | `originalPages`    | Original pages (full URL)      | `["https://ptengine.jp/app/select_project?from=login"]`      |
| Event      | `eventName`        | Event name                     | `["checkout_completed", "product_viewed"]`                   |
| Event      | `dimension`        | Custom dimension (cross-event) | Requires `eventVariant`                                      |
| Event      | `eventDimension`   | Custom dimension (event-bound) | Requires `eventName` and `eventVariant`                      |
| Conversion | `conversionName`   | Conversion name                | `["Purchase complete"]`                                      |

> Value examples are illustrative. For actual available values, call the [filter-values](#filter-values) endpoint.

**Custom-property filter (advanced)**

Use this only when your events carry custom properties (e.g. the `purchase` event has a `price` property) and you want to filter by those values. Two forms:

* **Bound to a specific event**: `{ "name": "eventDimension", "eventName": "purchase", "eventVariant": "price", "op": "include", "value": ["100"] }` — sessions where the `purchase` event has `price=100`
* **Cross-event lookup**: `{ "name": "dimension", "eventVariant": "price", "op": "include", "value": ["100"] }` — any event where `price=100`

**filter-values**

Returns the list of available values for a given filter field (e.g. all countries with data, all OS values, etc.). The returned values can be used **directly** as the `value` field of any query endpoint's filter.

**Request parameters**

| Param          | Required    | Type   | Description                                                                                                                                                          |
| -------------- | ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `profileId`    | yes         | string | Site ID (8 chars). Must match the profile bound to the API Key. Find it in the Ptengine URL, e.g. `https://www.ptengine.jp/app/{profileId}/home` contains `566d12f9` |
| `name`         | yes         | string | Filter field name, see [Dynamic-value fields](#dynamic-fields) above                                                                                                 |
| `startDate`    | no          | string | Start date: `YYYY-MM-DD` or `YYYY/MM/DD`. Defaults to last 30 days                                                                                                   |
| `endDate`      | no          | string | End date: `YYYY-MM-DD` or `YYYY/MM/DD`. Defaults to last 30 days                                                                                                     |
| `search`       | no          | string | Fuzzy-search keyword                                                                                                                                                 |
| `eventName`    | conditional | string | Only when `name="eventDimension"` (see Example 5 step 2)                                                                                                             |
| `eventVariant` | conditional | string | Only when `name="eventDimension"` (see Example 5 step 2)                                                                                                             |

**Example 1: regular field (e.g. country / os / browser)**

Request:

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/filter-values \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "name": "country",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

Response:

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "filterName": "country",
        "values": ["Japan", "China", "United States", "Singapore"]
    }
}
```

**Example 2: fuzzy search (`search`)**

To filter the values list by a keyword, pass `search`. For example, country names containing "Ja" (matches Japan, Jamaica, etc.):

Request:

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/filter-values \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "name": "country",
    "search": "Ja",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

Response:

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "filterName": "country",
        "values": ["Japan", "Jamaica"]
    }
}
```

**Example 3: list all event names (`name="eventName"`)**

Returns all event names that have data under the profile.

Request:

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/filter-values \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "name": "eventName",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

Response:

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "filterName": "eventName",
        "values": ["purchase", "add_to_cart", "gallery_item_impression"]
    }
}
```

**Example 4: list all custom event property names**

Returns all custom event property names under the profile.

Request:

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/filter-values \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "name": "dimension",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

Response:

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "filterName": "dimension",
        "values": ["price", "currency", "qty", "category"]
    }
}
```

**Example 5: values of a property under a specific event (`eventDimension`, two steps)**

`eventDimension` requires two steps: first use `name="eventDimension"` to fetch the list of "event + property" pairs, then pass the chosen `eventName` + `eventVariant` to fetch actual values.

**Step 1 — list (event, property) pairs:**

Request:

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/filter-values \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "name": "eventDimension",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

Response:

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "filterName": "eventDimension",
        "values": [
            { "eventName": "purchase", "eventVariant": "price" },
            { "eventName": "purchase", "eventVariant": "currency" },
            { "eventName": "add_to_cart", "eventVariant": "qty" }
        ]
    }
}
```

**Step 2 — pass the chosen eventName + eventVariant to fetch values:**

Request:

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/filter-values \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "name": "eventDimension",
    "eventName": "purchase",
    "eventVariant": "price",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

Response:

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "filterName": "eventDimension",
        "eventName": "purchase",
        "eventVariant": "price",
        "values": ["100", "200", "500"]
    }
}
```

***

### 2.2 Heatmap

> **Scope of this section**: heatmap-based page / block / element metrics — click rate, CTA clicks, first-screen exit rate, block exposure and drop-off. For unique visitors (UV), visits per visitor, average load time, or a ranking across many pages, see [§2.4 Data Center](#ep-datacenter).

Heatmap analytics — clicks and views on pages, blocks, and elements.

#### Request parameters

| Param             | Required    | Type      | Description                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ----------------- | ----------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `queryType`       | yes         | string    | Query type: `page_metrics` (heatmap page metrics), `page_insight` (page insight by dimension), `block_metrics` (block metrics), `element_metrics` (element metrics)                                                                                                                                                                                                                                                                        |
| `profileId`       | yes         | string    | Site ID (8 chars). Must match the profile bound to the API Key. Find it in the Ptengine URL, e.g. `https://www.ptengine.jp/app/{profileId}/home` contains `566d12f9`                                                                                                                                                                                                                                                                       |
| `url`             | yes         | string    | Target page URL                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `startDate`       | yes         | string    | Start date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                                                                                                                                                                                                                                                                                                   |
| `endDate`         | yes         | string    | End date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                                                                                                                                                                                                                                                                                                     |
| `deviceType`      | yes         | string    | Device filter, see [Device type rules](#device-type-rules)                                                                                                                                                                                                                                                                                                                                                                                 |
| `rangeType`       | no          | string    | URL matching mode. `MERGE_URL` (default) merges query params, ignoring URL differences; `URL` does exact match; `PAGE_GROUP` page-group dimension (requires `pageGroupId`, fetch via [Page groups](#page-groups))                                                                                                                                                                                                                          |
| `historyHeatmap`  | no          | string    | History heatmap snapshot ID. When provided, the query uses the config frozen at that snapshot; otherwise the latest config is used. For `block_metrics` / `element_metrics`: it affects all block/element metrics. For `page_metrics` / `page_insight`: only CTA metrics (`ctaClicks` / `ctaClickRate`) are affected — PV/UV/visits/bounce and other traffic metrics are unaffected. Fetch IDs via [Heatmap snapshots](#heatmap-snapshots) |
| `pageGroupId`     | no          | string    | Page group ID. Required when `rangeType=PAGE_GROUP`; fetch via [Page groups](#page-groups). In that case pass the page group base URL (the `defaultUrl` returned by page groups) as `url`                                                                                                                                                                                                                                                  |
| `engageConfig`    | no          | object    | Filter heatmap traffic by experiment (A/B test) version. `{ engageId, versionId, isControlGroup? }`: get `engageId` / `versionId` from `id` / `versions[].id` of `POST /v1/experience/list`; `isControlGroup` is optional. Omit `engageConfig` to count all traffic                                                                                                                                                                        |
| `metrics`         | no          | string\[] | If omitted, returns all metrics; if passed, only the specified ones. An unsupported field name returns 4018, with `hint` naming the field to use. See [Heatmap available metrics](#heatmap-metrics)                                                                                                                                                                                                                                        |
| `conversionNames` | no          | string\[] | Conversion name list, see §2.1 [Conversion Goals](#conversion-goals)                                                                                                                                                                                                                                                                                                                                                                       |
| `filters`         | no          | object\[] | Filter conditions, see §2.1 [Filter](#filter)                                                                                                                                                                                                                                                                                                                                                                                              |
| `lang`            | no          | string    | Language for labels: `EN` (default), `ZH`, `JP`. Invalid values fall back to `EN`                                                                                                                                                                                                                                                                                                                                                          |
| `funName`         | conditional | string    | Required when `queryType=page_insight`. Allowed: `terminalType` (device), `sourceType` (traffic source), `visitType` (new/returning), `aiName` (AI source), `utmCampaign`, `utmSource`, `utmMedium`, `utmTerm`, `utmContent`, `week`, `day`                                                                                                                                                                                                |

#### Query types

**`page_metrics` — Heatmap page metrics**

> **This set does not include** unique visitors (UV), visits per visitor, average visit duration, or average page load time. For those four, use Data Center `queryType: "overview"` with `topic: "metrics"` (see "Core metric overview"). Exclusive to this endpoint: click rate, CTA clicks, first-view exit rate.

Returns traffic, behavior, and conversion metrics for a specified page.

**Device types:** `ALL`, `PC`, `MOBILE`, `TABLET`

**`metrics` parameter:** if omitted, returns all metrics; if passed, only those specified.

**Conversion queries:** All query types support conversion. Add `conversions` (count) and/or `conversionRate` (rate) to `metrics` — they can be passed individually or together — and pass conversion names via `conversionNames`.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "page_metrics",
    "profileId": "566d12f9",
    "url": "https://ptengine.jp",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "deviceType": "ALL",
    "rangeType": "MERGE_URL",
    "metrics": ["pageView", "users", "visits", "bounceRate", "conversionRate"],
    "conversionNames": ["Purchase complete"],
    "lang": "EN"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "metrics": {
            "pageView": { "value": "15,234", "label": "Page Views (PV)", "description": "Number of times the page was viewed." },
            "users": { "value": "8,721", "label": "Unique Visitors (UV)", "description": "Number of unique visitors who viewed the page." },
            "visits": { "value": "10,532", "label": "Visits", "description": "Number of visits that viewed the page." },
            "bounceRate": { "value": "45.23%", "label": "Bounce Rate", "description": "Percentage of visitors who entered through this page and left without visiting any other page." },
            "conversionRate": { "value": "2.22%", "label": "Conversion Rate", "description": "Percentage of visits that completed a conversion after viewing this page." }
        },
        "conversionGoals": [
            {
                "conversionName": "Purchase complete",
                "conversionRate": { "value": "1.71%", "label": "Conversion Rate", "description": "Percentage of visits that completed a conversion after viewing this page." }
            }
        ]
    },
    "meta": {
        "queryType": "page_metrics",
        "profileId": "566d12f9",
        "url": "https://ptengine.jp",
        "dateRange": { "start": "2025-06-01", "end": "2025-06-30" },
        "deviceType": "ALL",
        "lang": "EN"
    }
}
```

> **Note:** `conversionGoals` has one entry per conversion goal, and each entry only carries the conversion metrics requested in `metrics`. The example above only has `conversionRate`, so each entry contains just the rate. To also return the count, add `conversions` to `metrics`.

**`page_insight` — One page broken down by dimension**

> Difference from Data Center `dimension_table`: this endpoint splits a **single page** by dimension (device, source, …); `dimension_table` ranks Top-N **across the whole site**.

Returns page metrics grouped by a specified dimension.

**Device types:** `ALL`, `PC`, `MOBILE`, `TABLET`

**Required:** `funName` (if `metrics` is omitted, returns all metrics)

**Allowed `funName` values:**

| funName        | Meaning                                           |
| -------------- | ------------------------------------------------- |
| `terminalType` | Group by device type (PC/Smart phone/Tablet)      |
| `sourceType`   | Group by source type (Direct/Search/Social/...)   |
| `visitType`    | Group by visit type (New visits/Returning visits) |
| `aiName`       | Group by AI name                                  |
| `utmCampaign`  | Group by UTM Campaign                             |
| `utmSource`    | Group by UTM Source                               |
| `utmMedium`    | Group by UTM Medium                               |
| `utmTerm`      | Group by UTM Term                                 |
| `utmContent`   | Group by UTM Content                              |
| `week`         | Group by week                                     |
| `day`          | Group by day                                      |

**Request example (group by device type):**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "page_insight",
    "profileId": "566d12f9",
    "url": "https://ptengine.jp",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "deviceType": "ALL",
    "rangeType": "MERGE_URL",
    "metrics": ["pageView", "users", "bounceRate"],
    "funName": "terminalType",
    "lang": "EN"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "insights": [
            {
                "name": "PC",
                "metrics": {
                    "pageView": { "value": "8,500", "label": "Page Views (PV)", "description": "Number of times the page was viewed." },
                    "users": { "value": "5,200", "label": "Unique Visitors (UV)", "description": "Number of unique visitors who viewed the page." },
                    "bounceRate": { "value": "38.00%", "label": "Bounce Rate", "description": "Percentage of visitors who entered through this page and left without visiting any other page." }
                },
                "conversionGoals": []
            },
            {
                "name": "Mobile",
                "metrics": {
                    "pageView": { "value": "5,800", "label": "Page Views (PV)", "description": "Number of times the page was viewed." },
                    "users": { "value": "3,100", "label": "Unique Visitors (UV)", "description": "Number of unique visitors who viewed the page." },
                    "bounceRate": { "value": "55.00%", "label": "Bounce Rate", "description": "Percentage of visitors who entered through this page and left without visiting any other page." }
                },
                "conversionGoals": []
            },
            {
                "name": "Tablet",
                "metrics": {
                    "pageView": { "value": "934", "label": "Page Views (PV)", "description": "Number of times the page was viewed." },
                    "users": { "value": "421", "label": "Unique Visitors (UV)", "description": "Number of unique visitors who viewed the page." },
                    "bounceRate": { "value": "42.15%", "label": "Bounce Rate", "description": "Percentage of visitors who entered through this page and left without visiting any other page." }
                },
                "conversionGoals": []
            }
        ]
    }
}
```

**`block_metrics` — Block metrics**

Returns metrics and screenshot URLs for each block (section) on a page. Requires that the page has been scanned and blocks configured in the product.

**Device types:** Must be `PC`, `MOBILE`, or `TABLET`. **`ALL` is not supported.**

**`metrics` parameter:** optional. If omitted, returns all metrics; if passed, only those specified. `blockName` and `screenshotUrl` are always returned.

**Available metrics:** `impression`, `impressionRate`, `avgDuration`, `dropoff`, `dropoffRate`, `conversions`, `conversionRate`

**stayTimeFilter:** optional, block dwell time filter (seconds), default 5 seconds.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "block_metrics",
    "profileId": "566d12f9",
    "url": "https://ptengine.jp",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "deviceType": "PC",
    "rangeType": "MERGE_URL",
    "lang": "EN"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "blocks": [
            {
                "blockName": "Hero banner",
                "screenshotUrl": "https://cdn.example.com/screenshot/block1.png",
                "metrics": {
                    "impression": { "value": "12,000", "label": "Impression", "description": "PVs where users started seeing the current block." },
                    "impressionRate": { "value": "95.00%", "label": "Impression Rate", "description": "Share of PVs where users started seeing the current block." },
                    "avgDuration": { "value": "5s", "label": "Avg. Dwell Time", "description": "Average dwell time on this block after users stop scrolling." },
                    "dropoff": { "value": "800", "label": "Dropoff", "description": "PVs that left the current block without clicking through or converting." },
                    "dropoffRate": { "value": "6.70%", "label": "Dropoff Rate", "description": "Share of PVs that left the current block." }
                },
                "conversionGoals": []
            }
        ]
    }
}
```

**`element_metrics` — Element metrics**

Returns metrics for each tracked element on a page. Requires page scanning and element configuration in the product.

**Device types:** Must be `PC`, `MOBILE`, or `TABLET`. **`ALL` is not supported.**

**`metrics` parameter:** optional. If omitted, returns all metrics; if passed, only those specified. `elementName` is always returned.

**Available metrics:** `impression`, `impressionRate`, `click`, `clickRate`, `conversions`, `conversionRate`

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "element_metrics",
    "profileId": "566d12f9",
    "url": "https://ptengine.jp",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "deviceType": "PC",
    "rangeType": "MERGE_URL",
    "lang": "EN"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "elements": [
            {
                "elementName": "Signup button",
                "metrics": {
                    "impression": { "value": "10,500", "label": "Impression", "description": "PVs where users saw the current element." },
                    "impressionRate": { "value": "88.00%", "label": "Impression Rate", "description": "Share of PVs where users saw the current element." },
                    "click": { "value": "1,500", "label": "Click", "description": "Number of clicks on the current element." },
                    "clickRate": { "value": "14.30%", "label": "Click Rate", "description": "Clicks ÷ impressions." }
                },
                "conversionGoals": []
            }
        ]
    }
}
```

#### Advanced query examples

The examples below show the three optional fields `historyHeatmap`, `PAGE_GROUP`, and `engageConfig` (combinable with any `queryType`).

**Example 1 — Metrics for a history heatmap snapshot** (`historyHeatmap`; snapshot IDs from [Heatmap snapshots](#heatmap-snapshots))

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "block_metrics",
    "profileId": "566d12f9",
    "url": "https://ptengine.jp",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "deviceType": "PC",
    "historyHeatmap": "1779886104229",
    "metrics": ["impression", "clickRate"]
  }'
```

**Example 2 — Query by page group** (`rangeType=PAGE_GROUP` + `pageGroupId`; page groups from [Page groups](#page-groups); pass the group's `defaultUrl` as `url`)

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "page_metrics",
    "profileId": "566d12f9",
    "rangeType": "PAGE_GROUP",
    "pageGroupId": "1753350824020",
    "url": "https://www.example.com/products",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "deviceType": "ALL",
    "metrics": ["pageView", "users", "visits"]
  }'
```

**Example 3 — Query by experiment version** (`engageConfig`; `engageId` / `versionId` from `POST /open-api/v1/experience/list`)

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "page_metrics",
    "profileId": "566d12f9",
    "url": "https://ptengine.jp",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "deviceType": "ALL",
    "engageConfig": {
      "engageId": "abc123",
      "versionId": "abc123_v1",
      "isControlGroup": false
    },
    "metrics": ["pageView", "users", "conversionRate"],
    "conversionNames": ["Purchase completed"]
  }'
```

#### Heatmap available metrics

**Heatmap page metrics (for `page_metrics` and `page_insight`)**

Use the field names below in the `metrics` array.

#### Traffic

| Field           | Description                                           | Type  |
| --------------- | ----------------------------------------------------- | ----- |
| `visits`        | Number of visits that viewed the page                 | value |
| `pageView`      | Number of times the page was viewed                   | value |
| `users`         | Number of unique visitors who viewed the page         | value |
| `newVisitsRate` | Percentage of new visits that viewed the page         | rate  |
| `entrances`     | Number of visits where this page was the landing page | value |

#### Behavior

| Field           | Description                                                                                                     | Type    |
| --------------- | --------------------------------------------------------------------------------------------------------------- | ------- |
| `fvRate`        | Percentage of visitors who didn't scroll, convert, or navigate after entering. High value = hero doesn't engage | rate    |
| `avgTimeOnPage` | Average time spent on the page. Measures how long content keeps visitors engaged                                | time    |
| `clicks`        | Total clicks on the page, regardless of whether the target is a link                                            | value   |
| `clickRate`     | Clicks per PV. Use it to gauge engagement                                                                       | rate    |
| `ctaClicks`     | Clicks on key CTAs on the page. Set key elements as CTAs in the heatmap                                         | value   |
| `ctaClickRate`  | CTA click rate = CTA clicks / PV                                                                                | rate    |
| `bounceRate`    | Percentage of visitors who entered through this page and left without visiting any other page                   | rate    |
| `avgPageView`   | Average number of pages viewed by visitors who landed on this page                                              | decimal |

#### Conversion

| Field            | Description                                                                                                               | Type  |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------- | ----- |
| `conversions`    | Number of visits that viewed this page and completed a conversion                                                         | value |
| `conversionRate` | Percentage of visits that completed a conversion after viewing this page. Higher = greater conversion impact of this page | rate  |

> **Note:** Conversion queries must also pass conversion goal names via `conversionNames`.

**Block metrics (for `block_metrics`)**

If `metrics` is omitted, all are returned; if passed, only the specified ones. `blockName` and `screenshotUrl` are always returned.

| Field            | Description                                                                                                | Type  |
| ---------------- | ---------------------------------------------------------------------------------------------------------- | ----- |
| `blockName`      | Block name                                                                                                 | text  |
| `screenshotUrl`  | Block screenshot URL                                                                                       | text  |
| `impression`     | PVs where users started seeing the current block                                                           | value |
| `impressionRate` | Share of PVs where users started seeing the current block                                                  | rate  |
| `dropoff`        | PVs that left the current block without clicking through or converting                                     | value |
| `dropoffRate`    | Share of PVs that left the current block without clicking through or converting                            | rate  |
| `avgDuration`    | Average dwell time on this block after users stop scrolling. Longer dwell typically means greater interest | time  |
| `conversions`    | Visits that stayed on a content block for a specific time and completed a conversion                       | value |
| `conversionRate` | Share of visits with conversion among visits that stayed on a block for a specific time                    | rate  |

**Element metrics (for `element_metrics`)**

If `metrics` is omitted, all are returned; if passed, only the specified ones. `elementName` is always returned.

| Field            | Description                                                           | Type  |
| ---------------- | --------------------------------------------------------------------- | ----- |
| `elementName`    | Element name                                                          | text  |
| `impression`     | PVs where users started seeing the current element                    | value |
| `impressionRate` | Share of PVs where users started seeing the current element           | rate  |
| `click`          | Number of clicks on the current element                               | value |
| `clickRate`      | Clicks ÷ impressions. Higher click rate = more engaging element       | rate  |
| `conversions`    | Visits that clicked an element and completed a conversion             | value |
| `conversionRate` | Share of visits with conversion among visits that clicked the element | rate  |

#### Device type rules

| queryType         | Supported deviceType            | Notes                               |
| ----------------- | ------------------------------- | ----------------------------------- |
| `page_metrics`    | `ALL`, `PC`, `MOBILE`, `TABLET` | `ALL` returns all-device aggregates |
| `page_insight`    | `ALL`, `PC`, `MOBILE`, `TABLET` | `ALL` returns all-device aggregates |
| `block_metrics`   | `PC`, `MOBILE`, `TABLET`        | **`ALL` not supported**             |
| `element_metrics` | `PC`, `MOBILE`, `TABLET`        | **`ALL` not supported**             |

#### Block & element prerequisites

Before querying `block_metrics` or `element_metrics`, you must scan the page in the Ptengine product:

1. Open the target page in Ptengine Heatmap
2. Enable block / element detection
3. Save the configuration

If a page is not configured, the API returns `4008` (block not configured) or `4016` (element not configured).

#### Request examples

**Example 1: page traffic overview**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-a8Kd3mNx9Qr2Tf5Vb7Wj1Yp0Ls4Hn6Uc" \
  -d '{
    "queryType": "page_metrics",
    "profileId": "566d12f9",
    "url": "https://ptengine.jp",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "deviceType": "ALL",
    "rangeType": "MERGE_URL",
    "metrics": ["visits", "pageView", "users", "bounceRate", "avgTimeOnPage"],
    "lang": "EN"
  }'
```

**Example 2: page insight grouped by device type**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-a8Kd3mNx9Qr2Tf5Vb7Wj1Yp0Ls4Hn6Uc" \
  -d '{
    "queryType": "page_insight",
    "profileId": "566d12f9",
    "url": "https://ptengine.jp",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "deviceType": "ALL",
    "rangeType": "MERGE_URL",
    "metrics": ["pageView", "users", "bounceRate", "clickRate"],
    "funName": "terminalType",
    "lang": "EN"
  }'
```

**Example 3: mobile block analytics with Japan filter**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-a8Kd3mNx9Qr2Tf5Vb7Wj1Yp0Ls4Hn6Uc" \
  -d '{
    "queryType": "block_metrics",
    "profileId": "566d12f9",
    "url": "https://ptengine.jp",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "deviceType": "MOBILE",
    "rangeType": "MERGE_URL",
    "filters": [
      { "name": "country", "op": "include", "value": ["Japan"] }
    ],
    "lang": "EN"
  }'
```

**Example 4: page metrics for a specific conversion goal**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-a8Kd3mNx9Qr2Tf5Vb7Wj1Yp0Ls4Hn6Uc" \
  -d '{
    "queryType": "page_metrics",
    "profileId": "566d12f9",
    "url": "https://ptengine.jp",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "deviceType": "ALL",
    "rangeType": "MERGE_URL",
    "metrics": ["pageView", "conversions", "conversionRate"],
    "conversionNames": ["Purchase complete"],
    "lang": "EN"
  }'
```

**Example 5: PC element click analytics**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-a8Kd3mNx9Qr2Tf5Vb7Wj1Yp0Ls4Hn6Uc" \
  -d '{
    "queryType": "element_metrics",
    "profileId": "566d12f9",
    "url": "https://ptengine.jp",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "deviceType": "PC",
    "rangeType": "MERGE_URL",
    "lang": "EN"
  }'
```

#### Notes

* Time-type fields (e.g. page `avgTimeOnPage`, block `avgDuration`) are returned as readable strings with units (e.g. `"5s"`, `"1m 30s"`).
* Rate-type values are decimals (e.g. `bounceRate: 0.45` means 45%).
* The API's data source matches the Ptengine product UI; results should match.
* If the requested URL has never been captured under the profile, the API returns `200` but all metric values are `0`. No error.

#### Heatmap snapshots

List all available history heatmap snapshots (successfully saved; manual + auto-saved) under a given `profileId + url`. The returned `id` can be passed back to the heatmap query as `historyHeatmap` to query metrics tied to that frozen configuration.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/heatmap/snapshots \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "url": "https://ptengine.jp",
    "rangeType": "MERGE_URL"
  }'
```

**Request fields:**

| Field         | Required    | Type   | Description                                                                          |
| ------------- | ----------- | ------ | ------------------------------------------------------------------------------------ |
| `profileId`   | yes         | string | Profile ID; must match the API key                                                   |
| `url`         | conditional | string | Required unless `PAGE_GROUP` (PAGE\_GROUP queries by `pageGroupId`, no `url` needed) |
| `rangeType`   | no          | string | `URL` / `MERGE_URL` (default) / `PAGE_GROUP`                                         |
| `pageGroupId` | conditional | string | Required when `rangeType=PAGE_GROUP`                                                 |

**Response example:**

```json
{
    "code": 200,
    "data": {
        "snapshots": [
            {
                "id": "1779886104229",
                "name": "Pre-release v1.2",
                "note": "AB test baseline",
                "createTime": 1779886104229
            }
        ]
    }
}
```

**Field meanings:**

| Field        | Meaning                                                 |
| ------------ | ------------------------------------------------------- |
| `id`         | Snapshot ID (pass as `historyHeatmap` in heatmap query) |
| `name`       | Snapshot name                                           |
| `note`       | Note                                                    |
| `createTime` | Creation time (milliseconds)                            |

***

#### Capabilities

Returns the `queryType` values, metrics, dimensions, page-level scopes and known limitations supported by each query endpoint, in machine-readable form. It queries no data and requires no `profileId`.

Purpose: a caller (an AI Agent in particular) does not have to read this whole document — call this endpoint first to decide which endpoint to use and how to fill in the parameters. The content is generated from the same whitelists the endpoints validate against, so it cannot drift from the implementation.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/capabilities \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{ "lang": "EN" }'
```

**Request parameters:**

| Parameter | Required | Type   | Description                                                                                    |
| --------- | -------- | ------ | ---------------------------------------------------------------------------------------------- |
| `lang`    | no       | string | Language of the descriptive text: `EN` (default), `ZH`, `JP`. Field names are never translated |

**Response example (excerpt):**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "endpoints": [
            {
                "path": "/open-api/v1/datacenter/query",
                "purpose": "Site- or page-level traffic metrics: metric overview, dimension rankings, single-metric time series.",
                "queryTypes": ["overview", "dimension_table", "metric_curve"],
                "metrics": {
                    "overview": ["visits", "users", "pageView", "..."],
                    "dimension_table": ["visits", "users", "...", "entrances", "avgPageVisits"],
                    "metric_curve": ["visits", "users", "pageView", "..."]
                },
                "dimensions": {
                    "overview": ["metrics", "sources", "location", "device"],
                    "dimension_table": ["sourceType", "combinedPages", "originalPages", "..."]
                },
                "pageUrlDimensions": ["combinedPages", "originalPages", "entryCombinedPages", "entryOriginalPages"],
                "rangeTypes": ["SITE", "MERGE_URL", "URL", "PAGE_GROUP"],
                "granularities": ["hour", "day", "week", "month"],
                "maxRows": 1000,
                "limitations": ["Passing conversionNames with dimension combinedPages / originalPages / pageGroup returns 4018; use entryCombinedPages / entryOriginalPages instead."]
            }
        ],
        "metricSets": ["datacenter.overview", "datacenter.dimensionTable", "heatmap.page", "heatmap.block", "heatmap.element"],
        "filters": {
            "fields": ["deviceType", "os", "country", "sourceType", "..."],
            "eventFields": ["visitType", "originalPages", "..."],
            "enumValues": {
                "sourceType": ["Direct", "Search", "Social", "Referral", "Campaign", "AISearch"],
                "visitType": ["New visits", "Returning visits"],
                "deviceType": ["PC", "Mobile", "Tablet"],
                "exitType": ["Bounce visits", "Non-bounce visits"]
            }
        },
        "lookupEndpoints": [
            { "path": "/open-api/v1/page-groups", "method": "POST", "returns": "pageGroupId" },
            { "path": "/open-api/v1/conversion/goals", "method": "POST", "returns": "conversionName" }
        ]
    }
}
```

**Field reference:**

| Field                           | Description                                                                                             |
| ------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `endpoints[].path`              | Endpoint path                                                                                           |
| `endpoints[].purpose`           | One line on what the endpoint covers                                                                    |
| `endpoints[].queryTypes`        | Supported `queryType` values (omitted for endpoints without the concept)                                |
| `endpoints[].metrics`           | Available metrics; an object when they differ per `queryType`                                           |
| `endpoints[].dimensions`        | Available dimensions                                                                                    |
| `endpoints[].pageUrlDimensions` | Dimensions whose rows return `{ title, url }` instead of a string                                       |
| `endpoints[].rangeTypes`        | Supported page-level scopes; **absent means the endpoint is site-wide only**                            |
| `endpoints[].granularities`     | Time granularities                                                                                      |
| `endpoints[].maxRows`           | Maximum rows per query                                                                                  |
| `endpoints[].deviceTypes`       | Supported device types (Heatmap only)                                                                   |
| `endpoints[].limitations`       | Known unsupported combinations, so you do not have to discover them by trial and error                  |
| `metricSets`                    | All metric-set identifiers, see §2.1 [Metric sets](#ep-common)                                          |
| `filters`                       | Filterable fields; fields in `enumValues` have fixed values, others must be looked up via filter values |
| `lookupEndpoints`               | Where to look up each kind of ID or name, with `method` (only event/fields is GET)                      |

***

#### Page groups

List all page groups under the given `profileId` (shared by heatmap / insight). Use the returned `id` (page group ID) for page-group queries: in heatmap query pass `rangeType=PAGE_GROUP` + `pageGroupId`; for history heatmap snapshots pass `rangeType=PAGE_GROUP` + `pageGroupId`.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/page-groups \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9"
  }'
```

**Request fields:**

| Field       | Required | Type   | Description                        |
| ----------- | -------- | ------ | ---------------------------------- |
| `profileId` | yes      | string | Profile ID; must match the API key |

**Response example:**

```json
{
    "code": 200,
    "data": {
        "pageGroups": [
            {
                "id": "1753350824020",
                "name": "Product detail pages",
                "defaultUrl": "https://www.example.com/products"
            }
        ]
    }
}
```

**Field meanings:**

| Field        | Meaning                                                                    |
| ------------ | -------------------------------------------------------------------------- |
| `id`         | Page group ID (pass as `pageGroupId` when querying with `PAGE_GROUP`)      |
| `name`       | Page group name                                                            |
| `defaultUrl` | Page group default base URL (pass as `url` when querying with PAGE\_GROUP) |

***

### 2.3 Event

> **Scope of this section**: trigger count and session count for custom events, split by event properties and standard dimensions. Cannot be scoped to a single page; for page traffic metrics use [§2.4 Data Center](#ep-datacenter).

Event analytics. Query events by dimension, metric, and segment (the `filters` field in your request).

#### Request parameters

| Param        | Required | Type                  | Description                                                                                                                                                                                                                                                                                                                                     |
| ------------ | -------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `profileId`  | yes      | string                | Site ID (8 chars). Must match the profile bound to the API Key. Find it in the Ptengine URL, e.g. `https://www.ptengine.jp/app/{profileId}/home` contains `566d12f9`                                                                                                                                                                            |
| `startDate`  | yes      | string                | Start date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                                                                                                                                                                                                        |
| `endDate`    | yes      | string                | End date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                                                                                                                                                                                                          |
| `dimensions` | yes      | (string \| object)\[] | Group-by dimensions array; must include `"eventName"`. Up to 3 non-time dimensions + at most 1 time dimension (`day` / `hour` / `week` / `month`), matching the **Event > Segment** product page. Each item is a string (standard dimension name) or an object `{ name: "eventDimension", eventVariant: "<propName>" }` (custom event property) |
| `metrics`    | no       | string\[]             | Metric field names, defaults to `["eventCount"]`. Allowed: `eventCount`, `sessions`                                                                                                                                                                                                                                                             |
| `filters`    | no       | object\[]             | Segment (filter) conditions, see §2.1 [Filter](#filter)                                                                                                                                                                                                                                                                                         |

**Custom event properties**

If your events carry custom properties (e.g. the `purchase` event has a `price` property), you can group by or segment on those properties.

* **Group by property** — add to `dimensions`:

  ```json
  { "name": "eventDimension", "eventVariant": "price" }
  ```

  Results aggregate by `price` value.
* **Segment by property** — add to `filters`:

  ```json
  { "name": "eventDimension", "eventName": "purchase", "eventVariant": "price", "op": "include", "value": ["100"] }
  ```

  Only sessions where `purchase` event has `price=100`.
* **Always lock the event when segmenting** — when segmenting by property, add an extra eventName filter, otherwise the query doesn't know which event to anchor on:

  ```json
  { "name": "eventName", "op": "include", "value": ["purchase"] }
  ```

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/event/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "dimensions": ["eventName", "day", "country"],
    "metrics": ["eventCount", "sessions"],
    "filters": [
      { "name": "eventName", "op": "include", "value": ["purchase"] },
      { "name": "country", "op": "include", "value": ["Japan", "China"] },
      { "name": "visitType", "op": "include", "value": ["New visits"] },
      { "name": "deviceType", "op": "include", "value": ["PC", "Mobile"] },
      {
        "name": "eventDimension",
        "eventName": "purchase",
        "eventVariant": "price",
        "op": "include",
        "value": ["100", "200"]
      }
    ]
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "columns": [
            { "name": "eventName", "type": "dimension", "dataType": "STRING" },
            { "name": "day", "type": "dimension", "dataType": "DATE" },
            { "name": "country", "type": "dimension", "dataType": "STRING" },
            { "name": "eventCount", "type": "metric", "dataType": "INTEGER" },
            { "name": "sessions", "type": "metric", "dataType": "INTEGER" }
        ],
        "rows": [
            { "eventName": "purchase", "day": "2026-04-15", "country": "Japan", "eventCount": 320, "sessions": 250 }
        ]
    }
}
```

#### More examples

**a) Simplest — count by event name**

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/event/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "dimensions": ["eventName"]
  }'
```

**b) Time series — by day**

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/event/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "dimensions": ["eventName", "day"],
    "metrics": ["eventCount", "sessions"]
  }'
```

**c) Filter by conversion goal (fuzzy name match)**

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/event/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "dimensions": ["eventName", "conversionName"],
    "metrics": ["eventCount"],
    "filters": [
        { "name": "eventName", "op": "include", "value": ["purchase"] },
        { "name": "conversionName", "op": "include", "value": ["ptmind"] }
    ]
  }'
```

> `conversionName` matches all goals whose names contain `"ptmind"`. If nothing matches, returns `4012`.

**d) Custom event property — group + filter**

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/event/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "dimensions": ["eventName", { "name": "eventDimension", "eventVariant": "position" }],
    "metrics": ["eventCount"],
    "filters": [
        { "name": "eventName", "op": "include", "value": ["gallery_item_impression"] },
        {
            "name": "eventDimension",
            "eventName": "gallery_item_impression",
            "eventVariant": "position",
            "op": "include",
            "value": ["home"]
        }
    ]
  }'
```

> Both filters are required and serve different purposes: the standalone `eventName` filter locks the query to `gallery_item_impression` (aggregation scope); the `eventDimension` filter further segments by `position == "home"`.

**e) Source distribution — UTM + source type**

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/event/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "dimensions": ["eventName", "sourceType", "utmSource"],
    "metrics": ["eventCount", "sessions"],
    "filters": [
        { "name": "eventName", "op": "include", "value": ["purchase"] },
        { "name": "sourceType", "op": "include", "value": ["Search", "Campaign"] }
    ]
  }'
```

**f) New visitors + PC + Japan/China**

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/event/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "dimensions": ["eventName", "country"],
    "metrics": ["eventCount"],
    "filters": [
        { "name": "eventName", "op": "include", "value": ["purchase"] },
        { "name": "visitType", "op": "include", "value": ["New visits"] },
        { "name": "deviceType", "op": "include", "value": ["PC"] },
        { "name": "country", "op": "include", "value": ["Japan", "China"] }
    ]
  }'
```

**g) Exclude bounce sessions**

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/event/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "dimensions": ["eventName"],
    "metrics": ["eventCount", "sessions"],
    "filters": [{ "name": "exitType", "op": "exclude", "value": ["Bounce visits"] }]
  }'
```

#### Metadata

Returns all available metrics and dimensions (multi-language labels, optional `lang` switch).

**Request example:**

```bash
curl -X GET "https://xbackend.ptengine.com/open-api/v1/event/fields?lang=EN" \
  -H "x-api-key: pt-your-api-key"
```

**Response example (excerpt):**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "metrics": [
            { "field": "eventCount", "label": "Events", "description": "Number of times the event was triggered.", "dataType": "INTEGER" },
            { "field": "sessions", "label": "Sessions", "description": "Number of sessions in which the event was triggered.", "dataType": "INTEGER" }
        ],
        "dimensions": [
            { "field": "eventName", "label": "Event Name", "description": "Name of the event.", "dataType": "STRING", "category": "event" },
            { "field": "country", "label": "Country", "description": "Country.", "dataType": "STRING", "category": "geography" }
        ]
    }
}
```

#### Event available metrics

| Field        | Description                                         | dataType |
| ------------ | --------------------------------------------------- | -------- |
| `eventCount` | Number of times the event was triggered             | INTEGER  |
| `sessions`   | Number of sessions in which the event was triggered | INTEGER  |

#### Event available dimensions (for `dimensions[]` group-by)

| Field              | Description      |
| ------------------ | ---------------- |
| `eventName`        | Event Name       |
| `visitType`        | Visit type       |
| `exitType`         | Exit type        |
| `combinedPages`    | Entry page       |
| `conversionName`   | Conversion Name  |
| `day`              | Date             |
| `hour`             | Hour             |
| `week`             | Week             |
| `month`            | Month            |
| `sourceType`       | Source type      |
| `campaignUrl`      | Campaign URL     |
| `referralSource`   | Referral Website |
| `referralUrl`      | Referral URL     |
| `searchEngine`     | Search           |
| `socialNetwork`    | Social Media     |
| `socialUrl`        | Social URL       |
| `aiName`           | AI Search        |
| `utmCampaign`      | Campaign name    |
| `utmSource`        | Source           |
| `utmMedium`        | Medium           |
| `utmContent`       | Content          |
| `utmTerm`          | Term             |
| `deviceType`       | Device Type      |
| `deviceBrand`      | Brand            |
| `os`               | OS               |
| `osVersion`        | OS Version       |
| `browser`          | Browser          |
| `browserVersion`   | Browser Version  |
| `screenResolution` | Resolution       |
| `country`          | Country / Area   |
| `region`           | State / City     |

#### Notes

* `dimensions` is required and **must include the string `"eventName"`** — event queries must group by event name. You can include other dimensions and `eventDimension` objects alongside.
* **Dimension count limit:** up to 3 non-time dimensions + at most 1 time dimension (`day` / `hour` / `week` / `month`). Exceeding either limit returns `4018`.
* **When `eventName` filter is required:** if any of the following:

  * `dimensions` contains a non-`eventName`, non-time field (e.g. `country`, `sourceType`)
  * `dimensions` contains an `eventDimension` object
  * `filters` contains an `eventDimension` item

  Form: `{ "name": "eventName", "op": "include", "value": ["<event name>"] }`. Missing returns `4018`.

***

### 2.4 Data Center

> **Scope of this section**: traffic metrics for a site or a page — core metric overview, dimension rankings, single-metric time series. Click rate / CTA / first-screen exit rate belong to the heatmap, see [§2.2 Heatmap](#ep-heatmap); analysis of a conversion goal itself is in [§2.5 Conversion](#ep-conversion).

Site-wide analytics — site metrics / traffic sources / geo distribution / device, OS, browser distribution / view details by dimension.

#### Request parameters

| Param            | Required    | Type      | Description                                                                                                                                                                                                                                                                                                                                        |
| ---------------- | ----------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `queryType`      | yes         | string    | Query type: `overview` (summary data by topic), `dimension_table` (Top-N table grouped by a dimension), `metric_curve` (time series for a single metric)                                                                                                                                                                                           |
| `profileId`      | yes         | string    | Site ID (8 chars). Must match the profile bound to the API Key. Find it in the Ptengine URL, e.g. `https://www.ptengine.jp/app/{profileId}/home` contains `566d12f9`                                                                                                                                                                               |
| `startDate`      | yes         | string    | Start date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                                                                                                                                                                                                           |
| `endDate`        | yes         | string    | End date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                                                                                                                                                                                                             |
| `filters`        | no          | object\[] | Filter conditions, see §2.1 [Filter](#filter)                                                                                                                                                                                                                                                                                                      |
| `conversionName` | no          | string    | Filter metrics by a single conversion goal. **When omitted, returns metrics aggregated across all conversions.** Applies only to `dimension_table` (any dimension except `combinedPages` / `originalPages` / `pageGroup`) and `metric_curve` (when `metric` ∈ `conversions` / `conversionRate` / `conversionValue`); other scenarios return `4018` |
| `lang`           | no          | string    | Language for labels: `EN` (default), `ZH`, `JP`. Only affects `overview` with `topic = "metrics"`, and the `label` / `description` on metric columns of `dimension_table`. Invalid values fall back to `EN`                                                                                                                                        |
| `rangeType`      | no          | string    | Query scope. `SITE` (default, whole profile) / `MERGE_URL` (combined page, ignores URL parameter differences) / `URL` (original page, different parameters are different pages) / `PAGE_GROUP`                                                                                                                                                     |
| `url`            | conditional | string    | Target page URL. Required when `rangeType` is `MERGE_URL` or `URL`                                                                                                                                                                                                                                                                                 |
| `pageGroupId`    | conditional | string    | Page group ID. Required when `rangeType=PAGE_GROUP`; obtain it from the [page group list](#page-groups) endpoint                                                                                                                                                                                                                                   |

#### Query types

**`overview` — Summary data by topic**

Returns overview data by topic.

**Required:** `topic`. Allowed values: `metrics` / `sources` / `location` / `device`.

> For finer details (specific search engine / referral URL / campaign name, or OS / browser distribution, etc.), use `queryType: "dimension_table"` with the corresponding `dimension`.

**`topic = "metrics"` — Core metric overview**

> Besides the metric values, the response carries three self-describing fields: `data.metricSet` declares which metric set this is; `data.scope` echoes the query scope (`rangeType` / `grain`, plus `url` or `pageGroupId` for page-level queries); and every metric carries its own `grain` (`site` / `page` / `pageGroup`) and `canonical` (concept name). On a page-level query each metric's `description` gets a scope note appended.

Returns visits, unique visitors (UV), page views (PV), new/returning visit share, visits per visitor, page views per visitor, average visit duration, average page load time and bounce rate.

> This is what "basic metrics" refers to. For click rate / CTA clicks / first-view exit rate use Heatmap `queryType: "page_metrics"` (see "Heatmap page metrics") — that set has no UV, per-visitor metrics or load time.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/datacenter/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "overview",
    "topic": "metrics",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "filters": [{ "name": "country", "op": "include", "value": ["Japan"] }],
    "lang": "EN"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "topic": "metrics",
        "metricSet": "datacenter.overview",
        "scope": { "rangeType": "SITE", "grain": "site" },
        "metrics": {
            "visits": {
                "value": "12,500",
                "label": "Visits",
                "description": "The number of times a site has been visited, a visitor may visit multiple times, browsing multiple pages at a time."
            },
            "users": {
                "value": "8,900",
                "label": "Unique visitors (UV)",
                "description": "The number of visitors who visited the site during the time. A visitor who comes to the site multiple times will count as 1 visitor."
            },
            "pageView": {
                "value": "32,000",
                "label": "Page views (PV)",
                "description": "The number of times the page has been viewed."
            },
            "newVisitsRate": {
                "value": "65.00%",
                "label": "% New visits",
                "description": "The percentage of visits that first time come to the site relative to the total number of visits."
            },
            "returnVisitsRate": {
                "value": "35.00%",
                "label": "% Returning visits",
                "description": "The percentage of visits that have visited the site before relative to the total number of visits."
            },
            "avgPageView": {
                "value": "2.56",
                "label": "PV / UV",
                "description": "The average pageviews a visitor viewed your pages. You can know how deep a visitor visits the site."
            },
            "avgVisits": {
                "value": "1.40",
                "label": "Visits / UV",
                "description": "The average times a visitor visits the site. You can know if most visitors will back to the site."
            },
            "avgVisitDuration": {
                "value": "3m 7s",
                "label": "Visit duration",
                "description": "The average duration of visits on the site. You can know if the site content attracts visitors to stay longer."
            },
            "avgLoadTime": {
                "value": "4s",
                "label": "Avg. page load time",
                "description": "The average time the page loaded. The longer the load time, the more likely to lose visitors."
            },
            "bounceRate": {
                "value": "42.00%",
                "label": "% Bounce",
                "description": "The percentage of visits that viewed only 1 page then left. You can know if the landing page attracts users to visit further pages."
            }
        }
    }
}
```

**`topic = "sources"` — Traffic sources**

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/datacenter/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "overview",
    "topic": "sources",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "topic": "sources",
        "totalVisits": 12500,
        "rows": [
            { "sourceType": "Direct", "visits": 5200 },
            { "sourceType": "Search", "visits": 3100 },
            { "sourceType": "Social", "visits": 1800 },
            { "sourceType": "Referral", "visits": 1500 },
            { "sourceType": "Campaign", "visits": 700 },
            { "sourceType": "AISearch", "visits": 200 }
        ]
    }
}
```

**`topic = "location"` — Geo distribution**

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/datacenter/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "overview",
    "topic": "location",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "topic": "location",
        "rows": [
            { "country": "Japan", "state": "Tokyo", "visits": 4200 },
            { "country": "Japan", "state": "Osaka", "visits": 1800 },
            { "country": "China", "state": "Shanghai", "visits": 1500 },
            { "country": "United States", "state": "California", "visits": 900 }
        ]
    }
}
```

**`topic = "device"` — Device distribution**

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/datacenter/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "overview",
    "topic": "device",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "topic": "device",
        "rows": [
            {
                "deviceType": "PC",
                "visits": 7800,
                "osVersion": [
                    { "name": "Windows 10", "visits": 5200 },
                    { "name": "Windows 11", "visits": 1800 }
                ],
                "resolution": [
                    { "name": "1920x1080", "visits": 3200 },
                    { "name": "1366x768", "visits": 2100 }
                ],
                "browserVersion": [
                    { "name": "Chrome 120", "visits": 4500 },
                    { "name": "Safari 17", "visits": 800 }
                ]
            },
            {
                "deviceType": "Mobile",
                "visits": 3600,
                "osVersion": [
                    { "name": "iOS 17", "visits": 2100 },
                    { "name": "Android 14", "visits": 1500 }
                ],
                "brand": [
                    { "name": "Apple", "visits": 2100 },
                    { "name": "Samsung", "visits": 900 }
                ],
                "browserVersion": [
                    { "name": "Safari 17", "visits": 2100 },
                    { "name": "Chrome Mobile 120", "visits": 1300 }
                ]
            },
            {
                "deviceType": "Tablet",
                "visits": 1100,
                "osVersion": [{ "name": "iPadOS 17", "visits": 900 }],
                "brand": [{ "name": "Apple", "visits": 900 }],
                "browserVersion": [{ "name": "Safari 17", "visits": 900 }]
            }
        ]
    }
}
```

**`dimension_table` — Top-N table grouped by a dimension**

Returns a Top-N table grouped by a single dimension.

**Required:** `dimension` — see [Available dimensions](#dc-dimensions).

**Optional:** `sortBy` (string) / `sortOrder` (`asc`/`desc`) / `limit` (1-1000, default 1000). Response is capped at 1000 rows.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/datacenter/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "dimension_table",
    "dimension": "country",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "sortBy": "visits",
    "sortOrder": "desc",
    "limit": 100,
    "lang": "EN"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "columns": [
            { "name": "country", "type": "dimension", "dataType": "STRING" },
            { "name": "visits", "type": "metric", "dataType": "INTEGER", "label": "Visits", "description": "The number of times a site has been visited, a visitor may visit multiple times, browsing multiple pages at a time." },
            { "name": "avgVisitDuration", "type": "metric", "dataType": "TIME", "label": "Visit duration", "description": "The average duration of visits on the site. You can know if the site content attracts visitors to stay longer." },
            { "name": "pageView", "type": "metric", "dataType": "INTEGER", "label": "Page views (PV)", "description": "The number of times the page has been viewed." },
            { "name": "newVisitsRate", "type": "metric", "dataType": "RATE", "label": "% New visits", "description": "The percentage of visits that first time come to the site relative to the total number of visits." },
            { "name": "conversionRate", "type": "metric", "dataType": "RATE", "label": "% Conversion", "description": "The percentage of visits that completed the specific conversion. Conversion rate = conversions / total visits. A higher conversion rate means this type of visit has better performance." },
            { "name": "conversions", "type": "metric", "dataType": "INTEGER", "label": "# Completions", "description": "The number of visits that completed the specific conversion." },
            { "name": "bounceRate", "type": "metric", "dataType": "RATE", "label": "% Bounce", "description": "The percentage of visits that viewed only 1 page then left. You can know if the landing page attracts users to visit further pages." }
        ],
        "rows": [
            {
                "country": "China",
                "visits": "619",
                "avgVisitDuration": "00:02:49",
                "pageView": "1,145",
                "newVisitsRate": "52.18%",
                "conversionRate": "96.28%",
                "conversions": "596",
                "bounceRate": "74.64%"
            },
            {
                "country": "Japan",
                "visits": "530",
                "avgVisitDuration": "00:00:08",
                "pageView": "553",
                "newVisitsRate": "99.81%",
                "conversionRate": "94.91%",
                "conversions": "503",
                "bounceRate": "96.04%"
            }
        ]
    }
}
```

> Each `metric` column carries `label` / `description` (language controlled by the `lang` field, defaults to `EN`). Metric values are formatted as strings to match the product UI columns: INTEGER with thousands separators (`"1,145"`), RATE as percentage (`"52.18%"`), `avgVisitDuration` as HH:MM:SS (`"00:02:49"`), `avgLoadTime` sub-second precision (`"2.45s"`). Parse the strings if you need the raw numeric values.

**Example: page list**

Top-N over "entry pages". Without `conversionName`, returns metrics aggregated across all conversions.

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/datacenter/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "dimension_table",
    "dimension": "entryCombinedPages",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "sortBy": "entrances",
    "sortOrder": "desc",
    "limit": 50
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "columns": [
            { "name": "url", "type": "dimension", "dataType": "STRING" },
            { "name": "title", "type": "dimension", "dataType": "STRING" },
            { "name": "entrances", "type": "metric", "dataType": "INTEGER", "label": "Entrances", "description": "The number of visits that the page was visited as a landing page." },
            { "name": "newVisitsRate", "type": "metric", "dataType": "RATE", "label": "% New visits", "description": "The percentage of visits that first time come to the site relative to the total number of visits." },
            { "name": "avgPageVisits", "type": "metric", "dataType": "NUMBER", "label": "Avg. pageviews", "description": "The average number of pages visited after entering from this page." },
            { "name": "avgVisitDuration", "type": "metric", "dataType": "TIME", "label": "Visit duration", "description": "The average duration of visits on the site." },
            { "name": "bounceRate", "type": "metric", "dataType": "RATE", "label": "% Bounce", "description": "The percentage of visits that viewed only 1 page then left." },
            { "name": "conversions", "type": "metric", "dataType": "INTEGER", "label": "# Completions", "description": "The number of visits that completed the specific conversion." },
            { "name": "conversionRate", "type": "metric", "dataType": "RATE", "label": "% Conversion", "description": "The percentage of visits that completed the specific conversion." }
        ],
        "rows": [
            { "url": "https://ptengine.jp", "title": "Ptengineウェブ運営All-in-Oneプラットフォーム | ウェブの改善や改善業務はこれひとつで完結", "entrances": "253", "newVisitsRate": "71.15%", "avgPageVisits": "1.29", "avgVisitDuration": "00:01:55", "bounceRate": "84.58%", "conversions": "253", "conversionRate": "100.00%" },
            { "url": "https://ptengine.jp/app/login", "title": "ログイン | Ptengine", "entrances": "186", "newVisitsRate": "31.18%", "avgPageVisits": "1.62", "avgVisitDuration": "00:01:24", "bounceRate": "44.62%", "conversions": "172", "conversionRate": "92.47%" }
        ]
    }
}
```

> Page-URL dimensions (`combinedPages` / `originalPages` / `entryCombinedPages` / `entryOriginalPages`) always return the columns `url` + `title`; the `pageGroup` dimension returns the group name as a string.
>
> **About `conversionName`**:
>
> * `entryCombinedPages` / `entryOriginalPages` (entry pages) **support** it: when supplied, the `conversions` and `conversionRate` columns are scoped to the selected goal (matching the "Select conversion" dropdown above the entry-page table in the product UI). Other metrics are unchanged.
> * `combinedPages` / `originalPages` / `pageGroup` (pages / page groups) **do not** support it: these dimensions do not compute conversion metrics, so passing `conversionName` returns `4018`.

**Example: filter metrics by a single conversion goal**

When `conversionName` is set, metrics (`conversions` / `conversionRate` etc.) are computed against the matched conversion only.

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/datacenter/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "dimension_table",
    "dimension": "entryCombinedPages",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "conversionName": "ptmind",
    "sortBy": "conversions",
    "sortOrder": "desc",
    "limit": 20
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "columns": [
            { "name": "url", "type": "dimension", "dataType": "STRING" },
            { "name": "title", "type": "dimension", "dataType": "STRING" },
            { "name": "entrances", "type": "metric", "dataType": "INTEGER", "label": "Entrances", "description": "The number of visits that the page was visited as a landing page." },
            { "name": "conversions", "type": "metric", "dataType": "INTEGER", "label": "# Completions", "description": "The number of visits that completed the specific conversion." },
            { "name": "conversionRate", "type": "metric", "dataType": "RATE", "label": "% Conversion", "description": "..." }
        ],
        "rows": [
            { "url": "https://ptengine.jp/app/signup", "title": "登録 | Ptengine", "entrances": "1,042", "conversions": "312", "conversionRate": "29.94%" },
            { "url": "https://ptengine.jp", "title": "Ptengineウェブ運営All-in-Oneプラットフォーム | ウェブの改善や改善業務はこれひとつで完結", "entrances": "815", "conversions": "187", "conversionRate": "22.94%" }
        ]
    }
}
```

**`metric_curve` — Time series for a single traffic metric (Data Center)**

> The Conversion endpoint has a `metric_curve` with the same name that only accepts conversion metrics (`conversions` / `conversionRate` / `conversionValue`). Use this one for traffic metrics such as visits, PV or bounce rate.

Returns a time series for a single metric.

**Required:** `metric`. Allowed values: see [Available metrics](#dc-metrics); `granularity`. Allowed values: `hour` / `day` / `week` / `month`. Response `time` field format: `YYYY-MM-DD` (or `YYYY-MM-DDTHH` for `hour` granularity).

> **`hour` granularity constraint**: `startDate` and `endDate` must be the same day; otherwise `4002` is returned. `day` / `week` / `month` have no such constraint.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/datacenter/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "metric_curve",
    "metric": "visits",
    "granularity": "day",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "filters": [{ "name": "deviceType", "op": "include", "value": ["PC"] }]
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "metric": "visits",
        "granularity": "day",
        "points": [
            { "time": "2026-04-01", "value": "420" },
            { "time": "2026-04-02", "value": "510" }
        ]
    }
}
```

#### Data Center available metrics

| Metric             | Type    | Description          |
| ------------------ | ------- | -------------------- |
| `visits`           | INTEGER | Visits               |
| `users`            | INTEGER | Unique visitors (UV) |
| `pageView`         | INTEGER | Page views (PV)      |
| `newVisitsRate`    | RATE    | % New visits         |
| `returnVisitsRate` | RATE    | % Returning visits   |
| `avgVisits`        | RATE    | Visits / UV          |
| `avgPageView`      | RATE    | PV / UV              |
| `avgVisitDuration` | TIME    | Visit duration       |
| `bounceRate`       | RATE    | % Bounce             |
| `avgLoadTime`      | TIME    | Avg. page load time  |
| `conversions`      | INTEGER | # Completions        |
| `conversionRate`   | RATE    | % Conversion         |
| `conversionValue`  | NUMBER  | Conversion value     |

#### Data Center available dimensions (for `queryType: "dimension_table"`)

> **The `combinedPages` / `originalPages` / `pageGroup` dimensions are not the same thing as the `rangeType` parameter.** Do not confuse them:
>
> * **Dimension**: splits the result into **one row per page** — for ranking and finding which pages perform best. Returns many pages at once.
> * **`rangeType`**: restricts the **whole query to a single page** — returns one set of numbers for that page only.
>
> "Give me the numbers for original page X" → `overview` + `rangeType: "URL"`. "Which original pages get the most visits?" → `dimension_table` + `dimension: "originalPages"`.
>
> `entryCombinedPages` / `entryOriginalPages` are **entry-page** dimensions, counting landings only — a different definition from the first two.

| Dimension            | Description          |
| -------------------- | -------------------- |
| `country`            | Country / Area       |
| `state`              | State / City         |
| `os`                 | OS                   |
| `osVersion`          | OS Version           |
| `browser`            | Browser              |
| `browserVersion`     | Browser Version      |
| `resolution`         | Resolution           |
| `brand`              | Brand                |
| `sourceType`         | Source Type          |
| `campaign`           | Campaign             |
| `campaignUrl`        | Campaign URL         |
| `referral`           | Referral             |
| `referralUrl`        | Referral URL         |
| `search`             | Search engine        |
| `socialMedia`        | Social media         |
| `socialUrl`          | Social URL           |
| `aiName`             | AI search source     |
| `adSource`           | UTM source           |
| `adName`             | UTM campaign         |
| `adMedium`           | UTM medium           |
| `adTerm`             | UTM term             |
| `adContent`          | UTM content          |
| `combinedPages`      | Combined pages       |
| `originalPages`      | Original pages       |
| `pageGroup`          | Page group           |
| `entryCombinedPages` | Entry combined pages |
| `entryOriginalPages` | Entry original pages |

***

### 2.5 Conversion

> **Scope of this section**: completions, conversion rate, conversion value, source breakdown and funnels for conversion goals. Site-wide only — it cannot be scoped to a page. For conversions on a specific page use [§2.2 Heatmap](#ep-heatmap).

Conversion goal analytics — completions, value, source distribution, funnel.

#### Request parameters

| Param            | Required    | Type      | Description                                                                                                                                                                                                                                                                                                   |
| ---------------- | ----------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `queryType`      | yes         | string    | Query type: `metrics` (conversion metrics), `metric_curve` (time trend), `sources_breakdown` (distribution by source), `ad_name_breakdown` (distribution by ad name), `ad_source_breakdown` (distribution by ad source), `funnel` (funnel), `regular` (positive goals list), `negative` (negative goals list) |
| `profileId`      | yes         | string    | Site ID (8 chars). Must match the profile bound to the API Key. Find it in the Ptengine URL, e.g. `https://www.ptengine.jp/app/{profileId}/home` contains `566d12f9`                                                                                                                                          |
| `startDate`      | yes         | string    | Start date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                                                                                                                                                                      |
| `endDate`        | yes         | string    | End date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                                                                                                                                                                        |
| `conversionName` | conditional | string    | Goal name (must hit exactly 1 goal, otherwise 4012). **Only required for `funnel`**; other queryTypes do NOT need `conversionName` (it will be ignored even if passed)                                                                                                                                        |
| `metric`         | conditional | string    | Required for `metric_curve` — `conversions` / `conversionRate` / `conversionValue`                                                                                                                                                                                                                            |
| `granularity`    | conditional | string    | Required for `metric_curve` — `hour` / `day` / `week` / `month`                                                                                                                                                                                                                                               |
| `filters`        | no          | object\[] | Filter (segment) conditions, see §2.1 [Filter](#filter)                                                                                                                                                                                                                                                       |
| `lang`           | no          | string    | Language for label/description: `EN` (default), `ZH`, `JP`. Currently only applied to `queryType = "metrics"` response. Invalid values fall back to `EN`                                                                                                                                                      |

#### Query types

**`metrics` — Conversion metrics**

Returns 5 metrics: **Completions / Conversion rate / Conversion value / Revenue / Loss**. Each metric is wrapped as `{ value, label }`; `label` honors the `lang` field.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/conversion/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "metrics",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30",
    "lang": "EN",
    "filters": [{ "name": "country", "op": "include", "value": ["Japan"] }]
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "queryType": "metrics",
        "metrics": {
            "conversions":     { "value": "214",     "label": "Completions" },
            "conversionRate":  { "value": "45.73%",  "label": "Conversion rate" },
            "conversionValue": { "value": "-21,100", "label": "Conversion value" },
            "revenue":         { "value": "0",       "label": "Revenue" },
            "loss":            { "value": "-21,100", "label": "Loss" }
        }
    }
}
```

**Field meanings:**

| Field             | Calculation                                                                 |
| ----------------- | --------------------------------------------------------------------------- |
| `conversions`     | Visits that completed any positive conversion (aggregated across all goals) |
| `conversionRate`  | `conversions / total visits`                                                |
| `conversionValue` | `revenue + loss` (may be negative)                                          |
| `revenue`         | Total revenue from positive conversion goals (cvValue ≥ 0)                  |
| `loss`            | Total loss from negative conversion goals (cvValue < 0), negative           |

**`metric_curve` — Time series for a single conversion metric (Conversion)**

> Conversion metrics only. For traffic metrics such as visits, PV or bounce rate use the Data Center `metric_curve`.

Returns the time series of a single conversion metric.

**Required:** `metric` — `conversions` / `conversionRate` / `conversionValue`; `granularity` — `hour` / `day` / `week` / `month`.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/conversion/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "metric_curve",
    "metric": "conversions",
    "granularity": "day",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "queryType": "metric_curve",
        "metric": "conversions",
        "granularity": "day",
        "points": [
            { "time": "2026-04-01", "value": "24" },
            { "time": "2026-04-02", "value": "35" }
        ]
    }
}
```

**`sources_breakdown` — Conversions by source (Conversion)**

> Conversion metrics only. For **traffic** metrics (visits, PV, bounce rate) broken down by source, use Data Center `dimension_table` with `dimension: "sourceType"` (or `campaign` / `referral` / `search` …).

Breakdown of conversions by traffic source.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/conversion/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "sources_breakdown",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "queryType": "sources_breakdown",
        "columns": [
            { "name": "sourceType", "type": "dimension", "dataType": "STRING" },
            { "name": "sourceName", "type": "dimension", "dataType": "STRING" },
            { "name": "conversions", "type": "metric", "dataType": "INTEGER" }
        ],
        "rows": [
            { "sourceType": "Direct", "sourceName": "no refer", "conversions": 1259 },
            { "sourceType": "Search", "sourceName": "google", "conversions": 13 },
            { "sourceType": "Referral", "sourceName": "https://example.com/", "conversions": 12 }
        ]
    }
}
```

**`ad_name_breakdown` — Distribution by ad name**

Breakdown of conversions by ad name (UTM Campaign).

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/conversion/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "ad_name_breakdown",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "queryType": "ad_name_breakdown",
        "columns": [
            { "name": "adName", "type": "dimension", "dataType": "STRING" },
            { "name": "conversions", "type": "metric", "dataType": "INTEGER" }
        ],
        "rows": [
            { "adName": "spring_sale_2026", "conversions": 320 },
            { "adName": "brand_awareness_q1", "conversions": 158 },
            { "adName": "retargeting_jp", "conversions": 92 }
        ]
    }
}
```

**`ad_source_breakdown` — Distribution by ad source**

Breakdown of conversions by ad source (UTM Source).

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/conversion/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "ad_source_breakdown",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "queryType": "ad_source_breakdown",
        "columns": [
            { "name": "adSource", "type": "dimension", "dataType": "STRING" },
            { "name": "conversions", "type": "metric", "dataType": "INTEGER" }
        ],
        "rows": [
            { "adSource": "google", "conversions": 420 },
            { "adSource": "facebook", "conversions": 180 },
            { "adSource": "newsletter", "conversions": 65 }
        ]
    }
}
```

**`funnel` — Funnel**

Returns per-step entries, dropoff, and conversion-to-next rate.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/conversion/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "funnel",
    "conversionName": "ptmind signup",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "queryType": "funnel",
        "conversionName": "ptmind signup",
        "conversionId": "1753350579776",
        "summary": {
            "totalConversions": 700,
            "totalConversionRate": "70.00%"
        },
        "steps": [
            {
                "stepId": 1, "entries": 1000, "external": 1000, "dropoff": 200,
                "conversionToNextRate": "80.00%",
                "entryPaths":   [{ "url": "https://example.com/landing", "visits": 600 }],
                "dropoffPaths": [{ "url": "Exit", "visits": 5 }, { "url": "https://example.com/other", "visits": 195 }]
            },
            {
                "stepId": 2, "entries": 800, "external": 0, "dropoff": 100,
                "conversionToNextRate": "87.50%",
                "entryPaths": [],
                "dropoffPaths": [{ "url": "https://example.com/other", "visits": 100 }]
            },
            {
                "stepId": 3, "entries": 700, "external": 0, "dropoff": 0,
                "conversionToNextRate": null,
                "entryPaths": [], "dropoffPaths": []
            }
        ]
    }
}
```

**Field meanings:**

| Field                         | Meaning                                                                        |
| ----------------------------- | ------------------------------------------------------------------------------ |
| `entries`                     | Entries to this step (`external + convert`)                                    |
| `external`                    | Visits that entered this step directly (not from the previous step)            |
| `dropoff`                     | Dropoff at this step = `entries − next step convert` (0 on the last step)      |
| `conversionToNextRate`        | Conversion rate to the next step (`null` on the last step)                     |
| `entryPaths`                  | URLs of external entry pages for this step, sorted by visits desc              |
| `dropoffPaths`                | URLs of dropoff pages for this step, sorted by visits desc; untracked → `Exit` |
| `summary.totalConversions`    | Final conversions (entries of the last step)                                   |
| `summary.totalConversionRate` | Last-step `entries` / sum of `external` across all steps                       |

**`regular` — Positive goals list**

Returns all "positive" (value ≥ 0) conversion goals with their metrics, one row per goal.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/conversion/query \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "queryType": "regular",
    "profileId": "566d12f9",
    "startDate": "2026-04-01",
    "endDate": "2026-04-30"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "data": {
        "queryType": "regular",
        "columns": [
            { "name": "conversionName", "type": "dimension", "dataType": "STRING" },
            { "name": "conversions", "type": "metric", "dataType": "INTEGER" },
            { "name": "conversionRate", "type": "metric", "dataType": "RATE" },
            { "name": "revenue", "type": "metric", "dataType": "NUMBER" }
        ],
        "rows": [
            { "conversionName": "ptmind signup", "conversions": "850", "conversionRate": "6.20%", "revenue": "0" },
            { "conversionName": "Download whitepaper", "conversions": "130", "conversionRate": "1.00%", "revenue": "0" }
        ]
    }
}
```

**`negative` — Negative goals list**

Same shape as `regular`. Returns all "negative" (value < 0, i.e. loss goals) conversion goals, with an extra `loss` column per row (absolute loss value).

#### Notes

* `conversionName` is only required for `funnel`; other queryTypes do NOT need `conversionName` (it will be ignored if passed).
* For `funnel`, `conversionName` must hit **exactly one** goal. If multiple match (e.g. `"ptmind"` matches both `"ptmind signup"` and `"ptmind purchase"`), it returns 4012 with the list of matches — use a more specific name.
* Use `POST /v1/conversion/goals` to list all goals before constructing your request.

***

## 3. Experience

> **Scope of this section**: impressions, clicks, goal completions and form submissions for popups, sticky bars and A/B tests, scoped to visitors who saw the experience. This is a different metric set from the traffic metrics in [§2.4 Data Center](#ep-datacenter); identically named fields such as `bounceRate` are not comparable.

### 3.1 List experiences

Returns basic info for all experiences in the profile, including goals and version lists. The `id`, `goalId`, and `versionId` used by subsequent endpoints all come from this response.

#### Request parameters

| Param       | Required | Type   | Description                                                                                                                                                          |
| ----------- | -------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `profileId` | yes      | string | Site ID (8 chars). Must match the profile bound to the API Key. Find it in the Ptengine URL, e.g. `https://www.ptengine.jp/app/{profileId}/home` contains `566d12f9` |

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/experience/list \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": [
        {
            "id": "6c3bad4b-d953-4088-9fcd-d8cbd976b3a2",
            "name": "Spring Promo Popup",
            "status": "RUNNING",
            "type": "POPUP",
            "goals": [{ "id": "6a8bedde-...", "name": "Purchase complete" }],
            "versions": [
                { "id": "a2696719-...", "name": "Control" },
                { "id": "b3c8f210-...", "name": "Pattern 1" }
            ]
        }
    ]
}
```

| Field      | Description                                                       |
| ---------- | ----------------------------------------------------------------- |
| `id`       | Experience ID, used as `id` param in report endpoints             |
| `name`     | Experience name                                                   |
| `status`   | Status: `DRAFT` / `RUNNING` / `PAUSE` / `SCHEDULED`               |
| `type`     | Type: `POPUP` / `STICKY_BAR` / `INLINE` / `ADVANCED` / `REDIRECT` |
| `goals`    | Goal list, used as `goalId` in A/B test endpoints                 |
| `versions` | Version list, used as `versionId` in form endpoint                |

***

### 3.2 List user properties

Returns the list of available user properties. When the insight endpoint uses `dimension: "userProperty"`, fetch `property` from this endpoint.

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/experience/user-properties \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": [
        { "name": "plan_name", "displayName": "Plan Name", "source": ["code"], "type": "STRING" },
        { "name": "signup_date", "displayName": "Signup Date", "source": ["default"], "type": "DATE" }
    ]
}
```

***

### 3.3 Experience overview metrics

Batch query metrics for multiple experiences.

#### Request parameters

| Param         | Required | Type      | Description                                                                                                                                                          |
| ------------- | -------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `profileId`   | yes      | string    | Site ID (8 chars). Must match the profile bound to the API Key. Find it in the Ptengine URL, e.g. `https://www.ptengine.jp/app/{profileId}/home` contains `566d12f9` |
| `experiences` | yes      | object\[] | Experience list (`id` + `name`, from the list endpoint)                                                                                                              |
| `metrics`     | no       | string\[] | Metric fields to return. If omitted, returns all defaults. Supported fields below                                                                                    |
| `lang`        | no       | string    | Response language: `EN` (default), `ZH`, `JP`                                                                                                                        |

**Supported `metrics` fields:**

| Field                | Description                                                    | Type    |
| -------------------- | -------------------------------------------------------------- | ------- |
| `viewedUsers`        | Number of users who viewed the experience                      | value   |
| `views`              | Number of times the experience was viewed                      | value   |
| `clickedUsers`       | Number of users who clicked a button or link in the experience | value   |
| `clickRate`          | Click ratio of users in the experience                         | rate    |
| `closedUsers`        | Number of users who closed the popup / sticky bar              | value   |
| `closeRate`          | Close ratio of users for popup / sticky bar                    | rate    |
| `formSubmittedUsers` | Number of users who submitted the form                         | value   |
| `formSubmitRate`     | Form submit ratio                                              | rate    |
| `goalReachedUsers`   | Users who reached a goal after viewing the experience          | value   |
| `goalReachRate`      | Goal-reach ratio of users who viewed the experience            | rate    |
| `goalStatus`         | Goal status by user share, property sum, or average            | value   |
| `avgVisitDuration`   | Average visit duration of users who viewed the experience      | time    |
| `avgPagesPerVisit`   | Average pages per visit                                        | decimal |
| `bounceRate`         | Bounce rate                                                    | rate    |
| `lastUpdatedTime`    | Last updated time                                              | text    |
| `lastUpdatedMember`  | Last updater                                                   | text    |
| `createdTime`        | Created time                                                   | text    |
| `createdMember`      | Creator                                                        | text    |
| `runningPeriod`      | Running period                                                 | text    |
| `tags`               | Custom property tags                                           | text    |

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/experience/report/overview \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "experiences": [
      { "id": "6c3bad4b-...", "name": "Spring Promo Popup" },
      { "id": "5bb77b97-...", "name": "Signup Guide" }
    ],
    "metrics": ["viewedUsers", "clickRate", "bounceRate"],
    "lang": "EN"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": [
        {
            "name": "Spring Promo Popup",
            "viewedUsers": { "value": 100, "label": "Viewed Users", "description": "Number of users who viewed the experience." },
            "clickRate": { "value": "5.00%", "label": "Click Rate", "description": "Click ratio of users in the experience." },
            "bounceRate": { "value": "42.86%", "label": "Bounce Rate", "description": "Bounce rate of visits that viewed the experience." }
        }
    ]
}
```

**All metrics return `{ value, label, description }`**. `label` and `description` follow `lang`.

***

### 3.4 Key metrics for a single experience

> Difference from 3.3: 3.3 queries many experiences at once for side-by-side comparison; this endpoint covers one experience.

Query overall metrics for a single experience.

#### Request parameters

| Param       | Required | Type   | Description                                                                                                                                                          |
| ----------- | -------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `profileId` | yes      | string | Site ID (8 chars). Must match the profile bound to the API Key. Find it in the Ptengine URL, e.g. `https://www.ptengine.jp/app/{profileId}/home` contains `566d12f9` |
| `id`        | yes      | string | Experience ID (from the list endpoint)                                                                                                                               |
| `startDate` | yes      | string | Start date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                             |
| `endDate`   | yes      | string | End date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                               |
| `lang`      | no       | string | Language for label/description: `EN` (default), `ZH`, `JP`                                                                                                           |

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/experience/report/metrics \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "id": "6c3bad4b-d953-4088-9fcd-d8cbd976b3a2",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "experienceName": "Spring Promo Popup",
        "items": [
            {
                "viewedUsers": { "value": 100, "label": "Viewed Users", "description": "..." },
                "views": { "value": 300, "label": "Views", "description": "..." },
                "clickedUsers": { "value": 50, "label": "Clicked Users", "description": "..." },
                "clickRate": { "value": "41.67%", "label": "Click Rate", "description": "..." },
                "goals": [
                    {
                        "name": "Purchase complete",
                        "reachedUsers": { "value": 5, "label": "Reached Users", "description": "..." },
                        "reachRate": { "value": "5.00%", "label": "Reach Rate", "description": "..." },
                        "value": { "value": null, "label": "Goal Status", "description": "..." }
                    }
                ],
                "avgVisitDuration": { "value": "06:33", "label": "Avg. Visit Duration", "description": "..." },
                "avgPagesPerVisit": { "value": "2.50", "label": "Avg. Pages per Visit", "description": "..." },
                "bounceRate": { "value": "42.86%", "label": "Bounce Rate", "description": "..." }
            }
        ]
    }
}
```

> **Note:** Returned metrics are filtered by experience type. For example, INLINE types don't return `clickedUsers` / `closedUsers`; experiences without forms don't return `formSubmittedUsers`.

***

### 3.5 Segment details

Query single-experience metrics grouped by dimension.

#### Request parameters

| Param          | Required    | Type   | Description                                                                                                                                                          |
| -------------- | ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `profileId`    | yes         | string | Site ID (8 chars). Must match the profile bound to the API Key. Find it in the Ptengine URL, e.g. `https://www.ptengine.jp/app/{profileId}/home` contains `566d12f9` |
| `id`           | yes         | string | Experience ID (from the list endpoint)                                                                                                                               |
| `startDate`    | yes         | string | Start date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                             |
| `endDate`      | yes         | string | End date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                               |
| `dimension`    | yes         | string | Primary dimension, see table below                                                                                                                                   |
| `subDimension` | no          | string | Secondary dimension                                                                                                                                                  |
| `property`     | conditional | object | Required when `dimension="userProperty"`. From the user-properties endpoint                                                                                          |
| `lang`         | no          | string | Language for label/description: `EN` (default), `ZH`, `JP`                                                                                                           |

**Allowed `dimension` values:**

| dimension      | Description      | Supports subDimension           |
| -------------- | ---------------- | ------------------------------- |
| `visitPage`    | Page             | ❌                               |
| `terminalType` | Device type      | ✅                               |
| `sourceType`   | Source type      | ✅                               |
| `utmCampaign`  | Campaign name    | ✅                               |
| `utmSource`    | Campaign source  | ✅                               |
| `utmMedium`    | Campaign medium  | ✅                               |
| `utmTerm`      | Campaign term    | ✅                               |
| `utmContent`   | Campaign content | ✅                               |
| `sourceUrl`    | Source URL       | ✅                               |
| `sourceHost`   | Source host      | ✅                               |
| `aiName`       | AI name          | ✅                               |
| `visitType`    | New / Returning  | ✅                               |
| `country`      | Country / Area   | ✅ (cannot combine with region)  |
| `region`       | Region           | ✅ (cannot combine with country) |
| `userProperty` | User property    | ❌ (requires `property`)         |

**userProperty example:** When `dimension` is `userProperty`, you must also pass `property`:

```json
{ "property": { "name": "plan_name", "source": ["code"], "type": "STRING" } }
```

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/experience/report/insight \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "id": "6c3bad4b-d953-4088-9fcd-d8cbd976b3a2",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "dimension": "terminalType",
    "subDimension": "visitType",
    "lang": "EN"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "experienceName": "Spring Promo Popup",
        "items": [
            {
                "name": "PC",
                "subName": "New visits",
                "viewedUsers": { "value": 80, "label": "Viewed Users", "description": "..." },
                "bounceRate": { "value": "38.00%", "label": "Bounce Rate", "description": "..." }
            },
            {
                "name": "Mobile",
                "subName": "Returning visits",
                "viewedUsers": { "value": 20, "label": "Viewed Users", "description": "..." },
                "bounceRate": { "value": "55.00%", "label": "Bounce Rate", "description": "..." }
            }
        ]
    }
}
```

***

### 3.6 A/B test results

A/B test results comparing each version, including uplift and probability-to-win.

#### Request parameters

| Param                 | Required    | Type    | Description                                                                                                                                                          |
| --------------------- | ----------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `profileId`           | yes         | string  | Site ID (8 chars). Must match the profile bound to the API Key. Find it in the Ptengine URL, e.g. `https://www.ptengine.jp/app/{profileId}/home` contains `566d12f9` |
| `id`                  | yes         | string  | Experience ID (from the list endpoint)                                                                                                                               |
| `startDate`           | yes         | string  | Start date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                             |
| `endDate`             | yes         | string  | End date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                               |
| `compareBy`           | yes         | string  | Comparison baseline metric, see below                                                                                                                                |
| `goalId`              | conditional | string  | Required when `compareBy="goalReached"` (from list endpoint goals)                                                                                                   |
| `showDeletedVersions` | no          | boolean | Include deleted versions, default false                                                                                                                              |
| `lang`                | no          | string  | Language for label/description: `EN` (default), `ZH`, `JP`                                                                                                           |

**Allowed `compareBy` values:**

| compareBy            | Description                                          |
| -------------------- | ---------------------------------------------------- |
| `viewedUsers`        | Users who viewed the experience                      |
| `clickedUsers`       | Users who clicked a button or link in the experience |
| `closedUsers`        | Users who closed the popup / sticky bar              |
| `formSubmittedUsers` | Users who submitted the form                         |
| `goalReached`        | Goal reached (requires `goalId`)                     |
| `avgVisitDuration`   | Average visit duration                               |
| `avgPagesPerVisit`   | Average pages per visit                              |
| `bounceRate`         | Bounce rate                                          |

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/experience/report/abtest/metrics \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "id": "6c3bad4b-d953-4088-9fcd-d8cbd976b3a2",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "compareBy": "goalReached",
    "goalId": "6a8bedde-084d-4828-b874-43568cd2f27f",
    "lang": "EN"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "experienceName": "Spring Promo Popup",
        "items": [
            {
                "name": "Control",
                "viewedUsers": { "value": 50, "label": "Viewed Users", "description": "..." },
                "goalReachedUsers": { "value": 5, "label": "Reached Users", "description": "..." },
                "goalReachRate": { "value": "10.00%", "label": "Reach Rate", "description": "..." },
                "uplift": { "value": "Baseline", "label": "Uplift", "description": "..." },
                "probabilityToBeBest": { "value": null, "label": "Probability to Win", "description": "..." }
            },
            {
                "name": "Pattern 1",
                "viewedUsers": { "value": 50, "label": "Viewed Users", "description": "..." },
                "goalReachedUsers": { "value": 8, "label": "Reached Users", "description": "..." },
                "goalReachRate": { "value": "16.00%", "label": "Reach Rate", "description": "..." },
                "uplift": { "value": "+60.00%", "label": "Uplift", "description": "..." },
                "probabilityToBeBest": { "value": "85.30%", "label": "Probability to Win", "description": "..." }
            }
        ]
    }
}
```

> * Response only contains the metric corresponding to `compareBy`, plus `uplift` + `probabilityToBeBest`.
> * Baseline `uplift` is `"Baseline"`. Other versions get a percentage (e.g. `"+50.00%"` or `"-10.00%"`).

***

### 3.7 A/B test results — segment details

A/B test version comparison grouped by dimension.

#### Request parameters

| Param                 | Required    | Type    | Description                                                                                                                                                          |
| --------------------- | ----------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `profileId`           | yes         | string  | Site ID (8 chars). Must match the profile bound to the API Key. Find it in the Ptengine URL, e.g. `https://www.ptengine.jp/app/{profileId}/home` contains `566d12f9` |
| `id`                  | yes         | string  | Experience ID (from the list endpoint)                                                                                                                               |
| `startDate`           | yes         | string  | Start date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                             |
| `endDate`             | yes         | string  | End date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                               |
| `compareBy`           | yes         | string  | Comparison metric (same as 3.6)                                                                                                                                      |
| `goalId`              | conditional | string  | Required when `compareBy="goalReached"`                                                                                                                              |
| `dimension`           | yes         | string  | Primary dimension (same as 3.5)                                                                                                                                      |
| `subDimension`        | no          | string  | Secondary dimension                                                                                                                                                  |
| `property`            | conditional | object  | Required when `dimension="userProperty"`                                                                                                                             |
| `showDeletedVersions` | no          | boolean | Include deleted versions, default false                                                                                                                              |
| `lang`                | no          | string  | Language for label/description: `EN` (default), `ZH`, `JP`                                                                                                           |

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/experience/report/abtest/insight \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "id": "6c3bad4b-d953-4088-9fcd-d8cbd976b3a2",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31",
    "compareBy": "goalReached",
    "goalId": "6a8bedde-...",
    "dimension": "terminalType",
    "lang": "EN"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "experienceName": "Spring Promo Popup",
        "items": [
            {
                "name": "PC",
                "versions": [
                    {
                        "name": "All versions",
                        "viewedUsers": { "value": 40, "label": "Viewed Users", "description": "..." },
                        "uplift": { "value": "Baseline", "label": "Uplift", "description": "..." }
                    },
                    {
                        "name": "Control",
                        "viewedUsers": { "value": 20, "label": "Viewed Users", "description": "..." },
                        "uplift": { "value": "Baseline", "label": "Uplift", "description": "..." }
                    },
                    {
                        "name": "Pattern 1",
                        "viewedUsers": { "value": 20, "label": "Viewed Users", "description": "..." },
                        "uplift": { "value": "+30.00%", "label": "Uplift", "description": "..." }
                    }
                ]
            }
        ]
    }
}
```

***

### 3.8 Form submissions

Detailed form submission data for a specific version.

#### Request parameters

| Param       | Required | Type   | Description                                                                                                                                                          |
| ----------- | -------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `profileId` | yes      | string | Site ID (8 chars). Must match the profile bound to the API Key. Find it in the Ptengine URL, e.g. `https://www.ptengine.jp/app/{profileId}/home` contains `566d12f9` |
| `id`        | yes      | string | Experience ID (from the list endpoint)                                                                                                                               |
| `versionId` | yes      | string | Version ID (from `versions` in the list endpoint)                                                                                                                    |
| `startDate` | yes      | string | Start date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                             |
| `endDate`   | yes      | string | End date: `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                                               |

**Request example:**

```bash
curl -X POST https://xbackend.ptengine.com/open-api/v1/experience/report/form \
  -H "Content-Type: application/json" \
  -H "x-api-key: pt-your-api-key" \
  -d '{
    "profileId": "566d12f9",
    "id": "6c3bad4b-d953-4088-9fcd-d8cbd976b3a2",
    "versionId": "a2696719-6375-456b-8dbc-7e3d273beb6d",
    "startDate": "2026-03-01",
    "endDate": "2026-03-31"
  }'
```

**Response example:**

```json
{
    "code": 200,
    "message": "OK",
    "data": {
        "columns": ["submittedAt", "Email", "Picture choice", "choice-test2"],
        "rows": [
            {
                "submittedAt": "2026/04/09 19:14:33",
                "Email": "test@example.com",
                "Picture choice": "Option 3",
                "choice-test2": ""
            },
            {
                "submittedAt": "2026/04/08 17:40:05",
                "Email": "user@example.com",
                "Picture choice": "",
                "choice-test2": "Option 1,Option 2"
            }
        ]
    }
}
```

> * `columns` is dynamic, generated from the actual form fields.
> * Each row in `rows` is a single submission. Empty fields are returned as empty strings.

***

### 3.9 Experience available metrics

#### Experience basic metrics (all types)

> These are **experience-level** metrics, scoped to visitors who saw the experience. They are not the same set as Data Center "Core metric overview". `bounceRate` / `avgVisitDuration` share the name across both but use different definitions — do not reconcile them.

| Field              | Format                        | Description          |
| ------------------ | ----------------------------- | -------------------- |
| `viewedUsers`      | number                        | Viewed users         |
| `views`            | number                        | Views                |
| `avgVisitDuration` | duration (`MM:SS`/`HH:MM:SS`) | Avg. visit duration  |
| `avgPagesPerVisit` | decimal (`"2.50"`)            | Avg. pages per visit |
| `bounceRate`       | percentage (`"42.86%"`)       | Bounce rate          |

#### Popup-class metrics (only POPUP / STICKY\_BAR / REDIRECT / ADVANCED with popup)

| Field          | Format     | Description   |
| -------------- | ---------- | ------------- |
| `clickedUsers` | number     | Clicked users |
| `clickRate`    | percentage | Click rate    |
| `closedUsers`  | number     | Closed users  |
| `closeRate`    | percentage | Close rate    |

#### Form-class metrics (only for experiences with forms configured)

| Field                | Format     | Description          |
| -------------------- | ---------- | -------------------- |
| `formSubmittedUsers` | number     | Form submitted users |
| `formSubmitRate`     | percentage | Form submit rate     |

#### Goal data

| Field                  | Description                                  |
| ---------------------- | -------------------------------------------- |
| `goals[].name`         | Goal name                                    |
| `goals[].reachedUsers` | Reached users                                |
| `goals[].reachRate`    | Reach rate                                   |
| `goals[].value`        | Reached value (null = counted by user share) |

***

## Appendix

### A. Error codes

| Code   | HTTP status | Description                                                                                                                                                            |
| ------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `4010` | 401         | Missing `x-api-key` header                                                                                                                                             |
| `4011` | 401         | Invalid API Key                                                                                                                                                        |
| `4030` | 403         | `profileId` does not match the profile bound to the API Key                                                                                                            |
| `4031` | 403         | API Key lacks query permission (scope `query` required)                                                                                                                |
| `4001` | 400         | Invalid `queryType`                                                                                                                                                    |
| `4002` | 400         | Invalid date format; must be `YYYY-MM-DD` or `YYYY/MM/DD`                                                                                                              |
| `4003` | 400         | Query date exceeds the plan's data retention period                                                                                                                    |
| `4006` | 400         | `page_insight` type requires `funName`                                                                                                                                 |
| `4007` | 400         | `block_metrics` requires specific deviceType (PC/MOBILE/TABLET); ALL not supported                                                                                     |
| `4008` | 400         | Page block not configured. Please scan the page in the product first                                                                                                   |
| `4009` | 400         | `element_metrics` requires specific deviceType (PC/MOBILE/TABLET); ALL not supported                                                                                   |
| `4012` | 400         | No matching conversion goal                                                                                                                                            |
| `4013` | 400         | Missing required field (the response message names the specific field)                                                                                                 |
| `4014` | 400         | Invalid `deviceType`; must be `ALL`, `PC`, `MOBILE`, or `TABLET`                                                                                                       |
| `4015` | 400         | Invalid `dimension` / `subDimension` (response message gives details)                                                                                                  |
| `4016` | 400         | Page element not configured. Please scan the page in the product first                                                                                                 |
| `4017` | 400         | Invalid `compareBy` (response message lists allowed values)                                                                                                            |
| `4018` | 400         | Invalid field (`/event/query` / `/insight/query` / `/conversion/query`: dimension / metric / queryType / topic / granularity not allowed, or dimension count exceeded) |
| `4019` | 400         | Invalid filter operator or value (must be `include`/`exclude`; `value` must be a non-empty array; sortOrder/limit out of range)                                        |
| `4040` | 404         | Experience not found (`id` does not exist under this profile)                                                                                                          |
| `4290` | 429         | Rate limit exceeded (per minute)                                                                                                                                       |
| `4291` | 429         | Rate limit exceeded (per day)                                                                                                                                          |
| `5000` | 500         | Internal server error                                                                                                                                                  |

The `message` is returned in the language requested by `lang` (body or query: EN/ZH/JP). If not specified or invalid, falls back to English.
