---
title: "Get sitewide conversion funnel"
method: POST
path: "/v25-10-beta/analytics/sitewide/conversion-funnel"
tags: ["Fetch Sitewide Analytics"]
---

# Get sitewide conversion funnel

`POST /v25-10-beta/analytics/sitewide/conversion-funnel`

## Request

- Base URL: `https://api.intelligems.io`
- URL: `https://api.intelligems.io/v25-10-beta/analytics/sitewide/conversion-funnel`
- Auth: API key in header `intelligems-access-token`
- TypeScript: <https://skmtc.dev/intelligems/apis/intelligems-external-api-v25-10-beta/docs/v25-10-beta/analytics/sitewide/conversion-funnel/post.ts> (a function with typed inputs; its response is checked against the schema)

Retrieve the sitewide conversion funnel as a Sankey graph: visitors flow from entry point → landing page → second page → cart → checkout → conversion. The step-1 entry-point nodes default to device type (Mobile / Desktop); set `entryPoint` to pivot step 1 on traffic source, visitor type, or source site instead. Top-5 bucketing per step plus catch-all `Other` / `Bounced` rollups happen server-side; the wire format is already aggregated.

`POST /v25-10-beta/analytics/sitewide/conversion-funnel`

### Request

| Field              | Required | Type                     | Notes                                                                                                                                                                                                                                                                                                                                                            |
| ------------------ | -------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `start`            | no       | ISO 8601 datetime string | Beginning of the analysis window. Defaults to the start of the day 30 days ago, in the store's timezone. Unlike the other sitewide endpoints, this default is day-aligned, not week-aligned.                                                                                                                                                                     |
| `end`              | no       | ISO 8601 datetime string | End of the analysis window. Defaults to now.                                                                                                                                                                                                                                                                                                                     |
| `filters`          | no       | filters object           | Shared sitewide filters that narrow the underlying dataset — `deviceType`, `visitorType`, `sourceSitesOrChannels`, `countryCodes`, `currencyCodes`, `onlyProductIds`, `landingPageFilters` (preferred; `landingPage` is deprecated), `landingPageTypes`, etc. See the Filters Reference for the full list.                                                       |
| `entryPoint`       | no       | string enum              | Pivots the funnel's step-1 entry-point dimension — it controls which buckets are _rendered_ at step 1, not which sessions are _included_. One of `"device_type"`, `"visitor_type"`, `"source_channel"`, `"source_site"`. Unrecognized values silently default to `"device_type"`. Renamed from `audience` (see note below). See "Entry point vs. filters" below. |
| `conversionFunnel` | no       | conversionFunnel object  | Funnel-specific filters. Stage flags + single landing/second page-type pins. See "Funnel-specific filters" below.                                                                                                                                                                                                                                                |

### The `conversionFunnel` object

All funnel-specific filtering lives in a single optional `conversionFunnel` object. All fields are optional; combine any subset.

**Stage flags** (boolean) — narrow the funnel input to sessions that hit a behavioral stage:

- `addedToCart` — sessions that added at least one item to cart
- `startedCheckout` — sessions that started checkout
- `converted` — sessions that converted
- `bounced` — sessions that bounced (no second page)
- `abandonedCart` — added to cart but did not convert
- `abandonedCheckout` — started checkout but did not convert
- `exitedBeforeAtc` — exited before adding to cart
- `viewedCollectionPage` — viewed a collection page
- `viewedProductPage` — viewed a product detail page

**Page-type pins** (landing-page enum) — pin the funnel to a single journey:

- `landingPageType` — restrict to sessions whose landing page was this type
- `secondPageType` — restrict to sessions whose second page was this type

Supported page-type values: `"PDP"`, `"Collection"`, `"Content"`, `"Blog"`, `"Homepage"`, `"Search"`, `"Cart"`, `"Other"`.

### Funnel-specific vs. shared filters

Two distinct layers of filtering, and they behave differently:

- **`filters.landingPageTypes`** (plural, array, inside the shared `filters` object) — narrows the _underlying dataset_ to sessions starting on any of the selected page types. Same as the other `/sitewide/*` endpoints.
- **`conversionFunnel.landingPageType`** / **`conversionFunnel.secondPageType`** (singular) — _pin the funnel itself_ to a specific journey, so a caller can see how the PDP → 2nd-page-PDP path converted in isolation.
- **`conversionFunnel` stage flags** (`addedToCart`, `converted`, etc.) — narrow the _input population_ to sessions that hit a specific behavioral stage. Equivalent to the clickable node filters in the Intelligems dashboard.

`conversionFunnel` reuses the same schema the Intelligems dashboard sends internally, so the external contract matches the dashboard's funnel filtering exactly.

### Entry point vs. filters

`entryPoint` and the shared `filters` look related but do **completely different** things. The simplest way to keep them straight:

> **`filters` change _which sessions are included_ in the funnel. `entryPoint` changes _which buckets are shown_ at step 1. They don't filter the same way — in fact, `entryPoint` doesn't filter at all.**

Concrete contrast:

- **`filters.deviceType: "mobile"`** → the funnel is computed over **only mobile sessions**. Every step in the response reflects mobile-only counts. Desktop sessions are gone from the dataset entirely.
- **`entryPoint: "device_type"`** → the **full dataset** (mobile + desktop) is funneled, but step 1 of the Sankey is **split into `"Mobile"` and `"Desktop"` nodes** so you can see how each device cohort flows down. Nothing is filtered out.

Two questions, two different answers:

| Question                                                                                | Use                                                 |
| --------------------------------------------------------------------------------------- | --------------------------------------------------- |
| "How does the funnel look **for mobile traffic specifically**?"                         | `filters: { deviceType: "mobile" }`                 |
| "How does the funnel **split** between Mobile and Desktop visitors at the entry point?" | `entryPoint: "device_type"`                         |
| "How does the funnel split by channel, restricted to mobile US traffic?"                | both: `entryPoint: "source_channel"` + `filters: …` |

They compose without conflict — `entryPoint` controls the rendering of step 1, `filters` controls what data feeds into the funnel in the first place.

#### Supported `entryPoint` values

| `entryPoint` value | Step-1 nodes                                                                                                                                     |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `"device_type"`    | `"Mobile"`, `"Desktop"`                                                                                                                          |
| `"visitor_type"`   | `"New"`, `"Returning"`                                                                                                                           |
| `"source_channel"` | Channel buckets: `"Paid Social"`, `"Paid Search"`, `"Direct"`, `"Organic Search"`, `"Email"`, `"Affiliate"`, … with top-5 + `"Other"` rollup     |
| `"source_site"`    | Referrer **display names** (`"Google"`, `"Facebook"`, `"Instagram"`, `"Klaviyo"`, `"TikTok"`, …) — not hostnames — with top-5 + `"Other"` rollup |

##### Reserved step-1 node names

- **`"Unknown"`** — emitted for any `entryPoint` when the session has no value for that dimension. It is a real bucket and counts toward the top-5 selection.
- **`"Misc"`** — emitted only for `source_site` and `source_channel`. Those two dimensions get the top-5 rollup, which reserves `"Other"` as the catch-all, so a session whose own taxonomy value is literally `Other` is renamed to `"Misc"` to keep the two distinct. `device_type` and `visitor_type` have no rollup and therefore never produce `"Misc"`.
- **`"Other"`** — the top-5 rollup catch-all on `source_site` and `source_channel` only. Not a value any session carries.

These four mirror the Customer Journey chart's audience selector exactly. The shared `AnalyticsAudienceType` enum also has `country_code` and `landing_page_full_path` values, but the funnel intentionally excludes those — they're not surfaced in the dashboard's funnel view, so the external API and MCP do not expose them either.

#### Fallback on unrecognized values

If `entryPoint` is set to any string outside the four supported values (e.g., `"country_code"`, `"channel"`, `"new_vs_returning"`, a typo), the request **does not 400** — the value silently falls back to `"device_type"` and a warning is logged server-side. This is deliberate so that LLM-driven callers that guess slightly-wrong dimension names still get a sensible funnel back instead of an opaque validation error.

When `entryPoint` is omitted entirely, the funnel uses its built-in default step-1 split (the same default the dashboard's Customer Journey chart starts on).

#### Renamed from `audience`

This parameter was named `audience` in earlier `v25-10-beta` builds. It was renamed to `entryPoint` to disambiguate it from the `audience` segmentation parameter on the `/analytics/sitewide/snapshot` and `/analytics/sitewide/timeseries` endpoints — on the funnel it pivots step-1 entry-point nodes, it does not segment KPIs. A legacy `audience` key sent to this endpoint is now **ignored** (the funnel falls back to its default step-1 split rather than erroring), so update existing integrations to send `entryPoint`.

### Response

Abbreviated example (one path through all six steps). Note every node referenced by a `link` appears in `nodes`, and step numbers are contiguous — a real response has more nodes/links per step:

```json
{
  "data": {
    "nodes": [
      { "name": "Mobile", "step": 1, "value": 8000, "pct": 0.8 },
      { "name": "Desktop", "step": 1, "value": 2000, "pct": 0.2 },
      { "name": "Landing: PDP", "step": 2, "value": 6500, "pct": 0.65 },
      { "name": "Bounced", "step": 3, "value": 4200, "pct": 0.42 },
      { "name": "2nd Page: PDP", "step": 3, "value": 2300, "pct": 0.23 },
      {
        "name": "Exited before Add to Cart",
        "step": 4,
        "value": 1500,
        "pct": 0.15
      },
      { "name": "Added to Cart", "step": 4, "value": 800, "pct": 0.08 },
      { "name": "Started Checkout", "step": 5, "value": 480, "pct": 0.048 },
      { "name": "Abandoned Cart", "step": 5, "value": 320, "pct": 0.032 },
      { "name": "Converted", "step": 6, "value": 300, "pct": 0.03 },
      { "name": "Abandoned Checkout", "step": 6, "value": 180, "pct": 0.018 }
    ],
    "links": [
      {
        "source": "Mobile",
        "target": "Landing: PDP",
        "step": 1,
        "value": 5200
      },
      {
        "source": "Desktop",
        "target": "Landing: PDP",
        "step": 1,
        "value": 1300
      },
      {
        "source": "Landing: PDP",
        "target": "Bounced",
        "step": 2,
        "value": 4200
      },
      {
        "source": "Landing: PDP",
        "target": "2nd Page: PDP",
        "step": 2,
        "value": 2300
      },
      {
        "source": "2nd Page: PDP",
        "target": "Exited before Add to Cart",
        "step": 3,
        "value": 1500
      },
      {
        "source": "2nd Page: PDP",
        "target": "Added to Cart",
        "step": 3,
        "value": 800
      },
      {
        "source": "Added to Cart",
        "target": "Started Checkout",
        "step": 4,
        "value": 480
      },
      {
        "source": "Added to Cart",
        "target": "Abandoned Cart",
        "step": 4,
        "value": 320
      },
      {
        "source": "Started Checkout",
        "target": "Converted",
        "step": 5,
        "value": 300
      },
      {
        "source": "Started Checkout",
        "target": "Abandoned Checkout",
        "step": 5,
        "value": 180
      }
    ]
  }
}
```

Every node a link references is present in `nodes`, steps run 1→6 with no gaps, and each `link.step` equals its source node's step. `pct` values are all fractions of the step-1 total (10,000 here).

- **`nodes`** — one entry per labeled state at each step. Ordered by `(step ascending, value descending)`.
  - `name` — node label (e.g. `"Mobile"`, `"Landing: PDP"`, `"Bounced"`, `"Added to Cart"`).
  - `step` — 1-indexed step position in the funnel.
  - `value` — visitor count at this node.
  - `pct` — share of step-1 visitors that reached this node, as a fraction in `[0, 1]` (not a percent).
- **`links`** — one entry per transition between adjacent step nodes. Ordered by `(step ascending, value descending)`.
  - `source` / `target` — node names on either end of the transition.
  - `step` — step of the source node.
  - `value` — visitor count traversing this link.

#### Server-side bucketing

At each step the server keeps the top 5 entries by traffic and rolls everything else into `"Other"`. Two special node names are reserved:

- `"Bounced"` — sessions that ended before reaching a second page.
- `"Landing: Other"` / `"2nd Page: Other"` — catch-all buckets for low-volume landing or second-page types.

This is the same shape the Intelligems dashboard renders; there is no "unbucketed" mode.

### Rate limits

Same rate limit as the other `/analytics/sitewide/*` endpoints. Aggregated, cacheable data — see the Rate Limiting Reference.

**Rate Limit:** 10 requests per 30s window, refilling 5 tokens every 30s.

## Request body

- object
  - `start` string, date-time: Start of analysis period as an ISO 8601 datetime string (e.g. '2025-01-01T00:00:00.000-05:00'). Defaults to the start of the day 30 days ago, in the store's timezone. Note the default differs per sitewide endpoint, so pass an explicit start if you need a specific window.
  - `end` string, date-time: End of analysis period as an ISO 8601 datetime string. Defaults to now.
  - `filters` object: Optional analytics filters object. See the Filters Reference for available filter fields (country, device, visitor type, sourceSitesOrChannels, landingPageTypes, etc.). These narrow the underlying dataset and are distinct from `entryPoint`, which pivots step 1.
    - `deviceType` 'any' | 'mobile' | 'desktop', nullable: Filter by device type. Options: 'any' (disables filter), 'mobile', 'desktop'. Omit or null to include all devices.
    - `visitorType` 'any' | 'new' | 'returning', nullable: Filter by visitor type. Options: 'any' (disables filter), 'new', 'returning'. Omit or null to include all visitors.
    - `customerType` 'new' | 'returning', nullable: Filter by customer type. Options: 'new', 'returning'. Omit or null to include all customers.
    - `sourceSitesOrChannels` string[]: Filter by traffic source channels. These 25 values are the complete accepted set — the channels the analytics service buckets sessions and orders into — and any other value is rejected with a 400: 'Instagram', 'Facebook', 'Google', 'Twitter', 'TikTok', 'Youtube', 'Klaviyo', 'Attentive', 'Postscript', 'Paid Shopping', 'Paid Search', 'Paid Social', 'Paid Video', 'Display', 'Paid Other', 'Organic Shopping', 'Organic Social', 'Organic Video', 'Organic Search', 'Other', 'Referral', 'Affiliate', 'SMS', 'Email', 'Direct'. Omit or pass an empty array for all channels — there is no 'any' sentinel.
    - `landingPage` object, nullable: DEPRECATED — use landingPageFilters instead, which supports multiple values and an and/or operator. This single-path filter is retained for backwards compatibility and still works, but new integrations should use landingPageFilters. Filter by landing page URL path. Object with: landingPageUrlPath (string|null — the path to match), landingPageUrlPathFilterType (match operator|null: 'equals', 'contains', 'startsWith', 'endsWith', 'doesNotEqual', 'doesNotContain', 'doesNotStartWith', 'doesNotEndWith', 'isNull', 'isNotNull'). REQUIRED COMBINATIONS (enforced with a 400): every operator except 'isNull'/'isNotNull' requires a non-empty landingPageUrlPath; 'isNull'/'isNotNull' take no path, so leave landingPageUrlPath null; and a landingPageUrlPath with no landingPageUrlPathFilterType is rejected. Omit both fields to apply no landing-page filter.
      - `landingPageUrlPath` string, nullable, required
      - `landingPageUrlPathFilterType` 'equals' | 'contains' | 'startsWith' | 'endsWith' | 'doesNotEqual' | 'doesNotContain' | 'doesNotStartWith' | 'doesNotEndWith' | 'isNull' | 'isNotNull', nullable, required
    - `landingPageFilters` object[]: Filter by landing page URL path with multi-value support. Recommended landing page filter (supersedes the deprecated landingPage field). Array of filter items, each with: filterType (match operator: 'equals', 'contains', 'startsWith', 'endsWith', 'doesNotEqual', 'doesNotContain', 'doesNotStartWith', 'doesNotEndWith', 'isNull', 'isNotNull') and values (array of strings to match against). REQUIRED COMBINATIONS (enforced with a 400): every operator except 'isNull'/'isNotNull' requires at least one non-empty entry in values — an omitted, empty, or blank-only values array is rejected rather than silently matching nothing. 'isNull'/'isNotNull' take no values; omit the field (an empty array is tolerated, real values are rejected). Multiple values within a single item are OR'd. How items in the array are combined is controlled by landingPageFiltersOperator.
      - `values` string[]
      - `filterType` 'equals' | 'contains' | 'startsWith' | 'endsWith' | 'doesNotEqual' | 'doesNotContain' | 'doesNotStartWith' | 'doesNotEndWith' | 'isNull' | 'isNotNull', required
    - `landingPageFiltersOperator` 'or' | 'and': How multiple items in landingPageFilters are combined. 'or' (default) — session matches if any filter item matches. 'and' — session must match every filter item.
    - `countryCodes` string[]: Filter by ISO 3166-1 alpha-2 country codes (e.g. ['US', 'GB', 'CA']). Omit or pass empty array for all countries.
    - `countryCodesFilterType` 'include' | 'exclude': How countryCodes should be matched: 'include' (only visitors in the listed countries) or 'exclude' (visitors in any country except the listed ones). Defaults to 'include' when omitted. Requires countryCodes to be a non-empty array.
    - `currencyCodes` string[]: Filter by ISO 4217 order currency codes (e.g. ['USD', 'GBP', 'CAD']). Matches the currency an order was placed in. Omit or pass empty array for all currencies.
    - `currencyCodesFilterType` 'include' | 'exclude': How currencyCodes should be matched: 'include' (only orders in the listed currencies) or 'exclude' (orders in any currency except the listed ones). Defaults to 'include' when omitted. Requires currencyCodes to be a non-empty array.
    - `maxZScore` union: Maximum Z-score threshold for outlier filtering on order revenue. Visitors with orders whose Z-score exceeds this value are excluded. Accepts number or numeric string. Null or omit to disable outlier filtering.
      - number
      - string
    - `onlyProductIds` string[]: Filter to orders containing at least one of these Shopify product IDs (numeric strings, e.g. ['1234567890', '9876543210']). Omit or pass an empty array for all products.
    - `landingPageTypes` string[]: Filter sessions by landing page types. An array of values from: 'PDP', 'Collection', 'Content', 'Blog', 'Homepage', 'Search', 'Cart', 'Other'. Omit or null to include all landing page types.
  - `entryPoint` 'device_type' | 'visitor_type' | 'source_channel' | 'source_site': Optional dimension that pivots the funnel's step-1 entry-point nodes. This does NOT filter the dataset — it only changes which buckets are rendered at step 1 (Mobile vs. Desktop, New vs. Returning, channel breakdown, source-site breakdown). To narrow the dataset to a single segment, use the `filters` object instead. Supported values: 'device_type' (Mobile vs Desktop), 'visitor_type' (New vs Returning), 'source_channel' (Paid Social, Paid Search, Direct, ...), 'source_site' (referrer host buckets). Any other value (typo, unsupported dimension, wrong type) silently falls back to 'device_type'. Mirrors the Customer Journey chart's audience selector in the Intelligems dashboard. NOTE: this parameter was named `audience` in earlier v25-10-beta builds (renamed to disambiguate it from the `audience` segmentation param on the snapshot/timeseries endpoints). A legacy `audience` key sent to this endpoint is now ignored — update integrations to `entryPoint`.
  - `conversionFunnel` object: Optional funnel-specific filters. Stage flags (addedToCart, startedCheckout, converted, bounced, abandonedCart, abandonedCheckout, exitedBeforeAtc, viewedCollectionPage, viewedProductPage) narrow the funnel input to sessions that hit that behavioral stage. landingPageType / secondPageType pin the funnel to a single landing-page or second-page journey (Supported page types: PDP, Collection, Content, Blog, Homepage, Search, Cart, Other). Equivalent to the clickable node filters in the Intelligems dashboard.
    - `abandonedCart` boolean
    - `abandonedCheckout` boolean
    - `addedToCart` boolean
    - `bounced` boolean
    - `converted` boolean
    - `exitedBeforeAtc` boolean
    - `startedCheckout` boolean
    - `viewedCollectionPage` boolean
    - `viewedProductPage` boolean
    - `landingPageType` 'PDP' | 'Collection' | 'Content' | 'Blog' | 'Homepage' | 'Search' | 'Cart' | 'Other'
    - `secondPageType` 'PDP' | 'Collection' | 'Content' | 'Blog' | 'Homepage' | 'Search' | 'Cart' | 'Other'

## Response `200`

OK

- object
  - `data` object, required: Sankey graph representation of the conversion funnel. Contains `nodes` (one per labeled state at each step) and `links` (transitions between adjacent steps). Server-side bucketing keeps only the top 5 entries per step plus catch-all 'Other' / 'Bounced' rollups.
    - `nodes` object[], required: Sankey nodes — one per labeled state at each step in the funnel. Ordered by (step ascending, value descending).
      - `name` string, required: Node label, e.g. 'Mobile', 'Landing: PDP', 'Bounced', 'Added to Cart'.
      - `step` number, required: 1-indexed step position in the funnel.
      - `value` number, required: Number of visitors at this node.
      - `pct` number, required: Share of step-1 visitors that reached this node, as a fraction in [0, 1] (not a percent).
    - `links` object[], required: Sankey links — one per transition between adjacent step nodes. Ordered by (step ascending, value descending).
      - `source` string, required: Name of the source node for this transition.
      - `target` string, required: Name of the target node for this transition.
      - `step` number, required: Step of the source node.
      - `value` number, required: Number of visitors traversing this link.

## Other responses

- `429`: Too Many Requests

## Changes

- **2026-11-06** `7b769b2f90b1`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/intelligems/apis/intelligems-external-api-v25-10-beta/changes/v25-10-beta/analytics/sitewide/conversion-funnel/post.md)

---

[API](https://skmtc.dev/intelligems/apis/intelligems-external-api-v25-10-beta.md) - [All operations](https://skmtc.dev/intelligems/apis/intelligems-external-api-v25-10-beta/llms.txt) - [OpenAPI document](https://skmtc.dev/intelligems/apis/intelligems-external-api-v25-10-beta/revisions/7b769b2f90b1?raw)
