> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usertour.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Get content analytics

> The response shape follows the content type (discriminated on `contentType`): flows report starts + completions and a per-step funnel with tooltip-target-missing counts; checklists starts + completions and per-task rows; launchers seen + activations; banners seen + dismissals; resource centers opens + block clicks; trackers users + occurrences of the tracked event. All with a per-day series. Defaults to the last 30 days, UTC.



## OpenAPI

````yaml /api-reference-v2/openapi.json get /v2/projects/{projectId}/content/{id}/analytics
openapi: 3.0.0
info:
  title: Usertour API v2
  description: >-
    Project-scoped v2 API. Authenticate with a personal API token — an opaque
    `utp_...` string (NOT a JWT: do not try to decode it), created in the
    Usertour app under Settings → API, sent as `Authorization: Bearer utp_...`.
  version: '2.0'
  contact: {}
servers:
  - url: https://api.usertour.io
security: []
tags: []
paths:
  /v2/projects/{projectId}/content/{id}/analytics:
    get:
      tags:
        - Analytics
      summary: Get content analytics
      description: >-
        The response shape follows the content type (discriminated on
        `contentType`): flows report starts + completions and a per-step funnel
        with tooltip-target-missing counts; checklists starts + completions and
        per-task rows; launchers seen + activations; banners seen + dismissals;
        resource centers opens + block clicks; trackers users + occurrences of
        the tracked event. All with a per-day series. Defaults to the last 30
        days, UTC.
      operationId: ApiAnalyticsController_contentAnalytics
      parameters:
        - name: id
          required: true
          in: path
          description: Content ID
          schema:
            type: string
        - name: projectId
          required: true
          in: path
          description: Project ID
          schema:
            type: string
        - name: environmentId
          required: true
          in: query
          description: >-
            Environment whose sessions to aggregate (content is project-level;
            pick the env).
          schema:
            type: string
        - name: startDate
          required: false
          in: query
          description: 'ISO date, inclusive. Default: 30 days ago.'
          schema:
            type: string
        - name: endDate
          required: false
          in: query
          description: 'ISO date, inclusive. Default: today.'
          schema:
            type: string
        - name: timezone
          required: false
          in: query
          description: 'IANA timezone used for the per-day bucketing. Default: UTC.'
          schema:
            type: string
      responses:
        '200':
          description: Content analytics — the shape follows the content type
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/FlowAnalyticsDto'
                  - $ref: '#/components/schemas/ChecklistAnalyticsDto'
                  - $ref: '#/components/schemas/LauncherAnalyticsDto'
                  - $ref: '#/components/schemas/BannerAnalyticsDto'
                  - $ref: '#/components/schemas/ResourceCenterAnalyticsDto'
                  - $ref: '#/components/schemas/TrackerAnalyticsDto'
                  - $ref: '#/components/schemas/AnnouncementAnalyticsDto'
                discriminator:
                  propertyName: contentType
        '400':
          description: >-
            Invalid request — E1017 validation (may carry `issues`; an invalid
            orderBy/limit is also E1017), E1015 invalid scope, E0003 invalid
            against current domain state.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '401':
          description: Missing or expired API key — E1010, E1020.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '403':
          description: >-
            Refused — E1000 invalid key, E1011 project not in token scope, E1012
            insufficient scope, E1029 environment not in token scope, E1032
            environment creation needs a token without env-targeted capabilities
            (its allowlist cannot cover a not-yet-existing environment).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '404':
          description: Content or environment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '429':
          description: >-
            Rate limit exceeded — E1013. The limit follows the project's plan
            (100/500/1000/3000 requests per minute); unknown credentials share a
            per-IP bucket. Every response also carries X-RateLimit-Limit /
            -Remaining / -Reset for pacing; a 429 adds the standard Retry-After
            header (seconds to back off).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
      security:
        - bearer: []
components:
  schemas:
    FlowAnalyticsDto:
      type: object
      properties:
        object:
          type: string
          enum:
            - contentAnalytics
        contentId:
          type: string
        environmentId:
          type: string
        startDate:
          type: string
        endDate:
          type: string
        timezone:
          type: string
        contentType:
          type: string
          enum:
            - flow
        uniqueStarts:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Distinct users who started it in the range.
        totalStarts:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Runs started in the range — one per session, so a user who ran it
            twice counts twice.
        uniqueCompletions:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Distinct users who reached the end of the flow (or an explicit
            completion step).
        totalCompletions:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Runs completed in the range.
        byDay:
          type: array
          items:
            type: object
            properties:
              date:
                type: string
                description: ISO date (bucketed in the requested timezone).
              uniqueStarts:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Distinct users who started it in the range.
              totalStarts:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Runs started in the range — one per session, so a user who ran
                  it twice counts twice.
              uniqueCompletions:
                type: integer
                minimum: 0
                maximum: 9007199254740991
              totalCompletions:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Runs completed in the range.
            required:
              - date
              - uniqueStarts
              - totalStarts
              - uniqueCompletions
              - totalCompletions
          description: >-
            Per-day activity: each row counts only that calendar day
            (increments, NOT a running total). Summing the `total*` rows
            reproduces the `total*` headline; a `unique*` row is distinct users
            WITHIN THAT DAY, so summing `unique*` rows over-counts a user active
            on several days — there is no daily series for range-wide unique
            users. Note the question-analytics nps/rating byDay uses the
            OPPOSITE convention (rolling-window cumulative).
        steps:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              cvid:
                type: string
              stepIndex:
                type: integer
                minimum: 0
                maximum: 9007199254740991
              type:
                type: string
                enum:
                  - tooltip
                  - modal
                  - hidden
                  - bubble
              uniqueViews:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Distinct users who saw this step. This is the funnel:
                  step-to-step drop-off is the difference between consecutive
                  rows’ uniqueViews.
              totalViews:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Runs in which this step was shown (re-visits within one run do
                  not add).
              uniqueCompletions:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Distinct users whose FLOW completion fired on this step — not
                  "users who advanced past it". Normally 0 on every step but the
                  last (or an explicit completion step); a 0 here says nothing
                  about that step’s success. Use uniqueViews for step
                  conversion.
              totalCompletions:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Flow completions attributed to this step — see
                  uniqueCompletions.
              uniqueTooltipTargetMissing:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Distinct users for whom this tooltip step's target element was
                  never found — the selector-health signal. Only meaningful on
                  tooltip steps; the field is present (and always 0) on other
                  step types to keep rows uniform.
              totalTooltipTargetMissing:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Runs in which the target element was never found.
            required:
              - name
              - cvid
              - stepIndex
              - type
              - uniqueViews
              - totalViews
              - uniqueCompletions
              - totalCompletions
              - uniqueTooltipTargetMissing
              - totalTooltipTargetMissing
      required:
        - object
        - contentId
        - environmentId
        - startDate
        - endDate
        - timezone
        - contentType
        - uniqueStarts
        - totalStarts
        - uniqueCompletions
        - totalCompletions
        - byDay
        - steps
    ChecklistAnalyticsDto:
      type: object
      properties:
        object:
          type: string
          enum:
            - contentAnalytics
        contentId:
          type: string
        environmentId:
          type: string
        startDate:
          type: string
        endDate:
          type: string
        timezone:
          type: string
        contentType:
          type: string
          enum:
            - checklist
        uniqueStarts:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Distinct users who started it in the range.
        totalStarts:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Runs started in the range — one per session, so a user who ran it
            twice counts twice.
        uniqueCompletions:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Distinct users who completed every visible task.
        totalCompletions:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Runs completed in the range.
        uniqueOpens:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Distinct users who expanded the checklist panel in the range — the
            denominator for per-task click/completion rates. Caveat: completion
            conditions evaluate regardless of expansion or task visibility (a
            condition-driven task completes for users who never opened the
            panel), so only click-completed tasks form a true funnel against
            this.
        totalOpens:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Panel expansions in the range — every expansion counts, so repeats
            by the same user add up.
        byDay:
          type: array
          items:
            type: object
            properties:
              date:
                type: string
                description: ISO date (bucketed in the requested timezone).
              uniqueStarts:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Distinct users who started it in the range.
              totalStarts:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Runs started in the range — one per session, so a user who ran
                  it twice counts twice.
              uniqueCompletions:
                type: integer
                minimum: 0
                maximum: 9007199254740991
              totalCompletions:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Runs completed in the range.
              uniqueOpens:
                type: integer
                minimum: 0
                maximum: 9007199254740991
              totalOpens:
                type: integer
                minimum: 0
                maximum: 9007199254740991
            required:
              - date
              - uniqueStarts
              - totalStarts
              - uniqueCompletions
              - totalCompletions
              - uniqueOpens
              - totalOpens
          description: >-
            Per-day activity: each row counts only that calendar day
            (increments, NOT a running total). Summing the `total*` rows
            reproduces the `total*` headline; a `unique*` row is distinct users
            WITHIN THAT DAY, so summing `unique*` rows over-counts a user active
            on several days — there is no daily series for range-wide unique
            users. Note the question-analytics nps/rating byDay uses the
            OPPOSITE convention (rolling-window cumulative).
        tasks:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              taskId:
                type: string
                description: >-
                  The task's stable identity — equals the checklist definition's
                  `data.items[].id` on the version; join on it to pair analytics
                  rows with task definitions.
              uniqueCompletions:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Distinct users who completed this task.
              totalCompletions:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Runs in which this task was completed.
              uniqueClicks:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Distinct users who clicked this task.
              totalClicks:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Task-click events (repeats included).
            required:
              - name
              - taskId
              - uniqueCompletions
              - totalCompletions
              - uniqueClicks
              - totalClicks
      required:
        - object
        - contentId
        - environmentId
        - startDate
        - endDate
        - timezone
        - contentType
        - uniqueStarts
        - totalStarts
        - uniqueCompletions
        - totalCompletions
        - uniqueOpens
        - totalOpens
        - byDay
        - tasks
    LauncherAnalyticsDto:
      type: object
      properties:
        object:
          type: string
          enum:
            - contentAnalytics
        contentId:
          type: string
        environmentId:
          type: string
        startDate:
          type: string
        endDate:
          type: string
        timezone:
          type: string
        contentType:
          type: string
          enum:
            - launcher
        uniqueSeen:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Distinct users whose launcher FIRST appeared in the range — counted
            from each user's first-ever seen event, so a range counts users
            NEWLY reached in it and a user first reached before the range never
            appears, no matter how often they still see the launcher. (Delivery
            shows a launcher once per user: one lifetime session.)
        newActivations:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Distinct users whose FIRST-EVER activation (click / hover, per the
            launcher setting) fell in the range. Later activations never
            re-count a user, so this pairs with uniqueSeen as a first-touch
            funnel. A user first reached in an earlier range who first activates
            now counts here but not in uniqueSeen, so per-range
            newActivations/uniqueSeen can exceed 1; over an all-time range it
            cannot.
        byDay:
          type: array
          items:
            type: object
            properties:
              date:
                type: string
                description: ISO date (bucketed in the requested timezone).
              uniqueSeen:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Distinct users whose launcher FIRST appeared in the range —
                  counted from each user's first-ever seen event, so a range
                  counts users NEWLY reached in it and a user first reached
                  before the range never appears, no matter how often they still
                  see the launcher. (Delivery shows a launcher once per user:
                  one lifetime session.)
              newActivations:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Distinct users whose FIRST-EVER activation (click / hover, per
                  the launcher setting) fell in the range. Later activations
                  never re-count a user, so this pairs with uniqueSeen as a
                  first-touch funnel. A user first reached in an earlier range
                  who first activates now counts here but not in uniqueSeen, so
                  per-range newActivations/uniqueSeen can exceed 1; over an
                  all-time range it cannot.
            required:
              - date
              - uniqueSeen
              - newActivations
          description: >-
            Per-day FIRST-TOUCH activity: each row counts the users whose first
            event of that kind fell on that calendar day. A user appears on
            exactly one day, so rows never double-count and summing them equals
            the range headline. Note the question-analytics nps/rating byDay
            uses a different convention (rolling-window cumulative).
      required:
        - object
        - contentId
        - environmentId
        - startDate
        - endDate
        - timezone
        - contentType
        - uniqueSeen
        - newActivations
        - byDay
    BannerAnalyticsDto:
      type: object
      properties:
        object:
          type: string
          enum:
            - contentAnalytics
        contentId:
          type: string
        environmentId:
          type: string
        startDate:
          type: string
        endDate:
          type: string
        timezone:
          type: string
        contentType:
          type: string
          enum:
            - banner
        uniqueSeen:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Distinct users whose banner FIRST appeared in the range — counted
            from each user's first-ever seen event, so a range counts users
            newly reached in it, not users who merely still had it on screen.
        uniqueDismissals:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Distinct users whose first dismissal fell in the range (counted from
            each user's first dismissal event; a banner is dismissed at most
            once per user).
        byDay:
          type: array
          items:
            type: object
            properties:
              date:
                type: string
                description: ISO date (bucketed in the requested timezone).
              uniqueSeen:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Distinct users whose banner FIRST appeared in the range —
                  counted from each user's first-ever seen event, so a range
                  counts users newly reached in it, not users who merely still
                  had it on screen.
              uniqueDismissals:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Distinct users whose first dismissal fell in the range
                  (counted from each user's first dismissal event; a banner is
                  dismissed at most once per user).
            required:
              - date
              - uniqueSeen
              - uniqueDismissals
          description: >-
            Per-day FIRST-TOUCH activity: each row counts the users whose first
            event of that kind fell on that calendar day. A user appears on
            exactly one day, so rows never double-count and summing them equals
            the range headline. Note the question-analytics nps/rating byDay
            uses a different convention (rolling-window cumulative).
      required:
        - object
        - contentId
        - environmentId
        - startDate
        - endDate
        - timezone
        - contentType
        - uniqueSeen
        - uniqueDismissals
        - byDay
    ResourceCenterAnalyticsDto:
      type: object
      properties:
        object:
          type: string
          enum:
            - contentAnalytics
        contentId:
          type: string
        environmentId:
          type: string
        startDate:
          type: string
        endDate:
          type: string
        timezone:
          type: string
        contentType:
          type: string
          enum:
            - resource-center
        uniqueOpens:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Distinct users who expanded the panel in the range.
        totalOpens:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Panel expansions in the range — every expansion counts, so repeats
            by the same user add up.
        uniqueClicks:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Distinct users who clicked a block inside the panel.
        totalClicks:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Block-click events in the range (repeats included). Normally equals
            the sum of the block rows' totalClicks; it can exceed that sum when
            clicks were recorded on blocks since removed from the published
            version.
        byDay:
          type: array
          items:
            type: object
            properties:
              date:
                type: string
                description: ISO date (bucketed in the requested timezone).
              uniqueOpens:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Distinct users who expanded the panel in the range.
              totalOpens:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Panel expansions in the range — every expansion counts, so
                  repeats by the same user add up.
              uniqueClicks:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Distinct users who clicked a block inside the panel.
              totalClicks:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Block-click events in the range (repeats included). Normally
                  equals the sum of the block rows' totalClicks; it can exceed
                  that sum when clicks were recorded on blocks since removed
                  from the published version.
            required:
              - date
              - uniqueOpens
              - totalOpens
              - uniqueClicks
              - totalClicks
          description: >-
            Per-day activity: each row counts only that calendar day
            (increments, NOT a running total). Summing the `total*` rows
            reproduces the `total*` headline; a `unique*` row is distinct users
            WITHIN THAT DAY, so summing `unique*` rows over-counts a user active
            on several days — there is no daily series for range-wide unique
            users. Note the question-analytics nps/rating byDay uses the
            OPPOSITE convention (rolling-window cumulative).
        blocks:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              blockId:
                type: string
              tabId:
                type: string
                description: >-
                  The tab's stable identity — group block rows by it (tabName
                  can be null or duplicated across tabs).
              tabName:
                type: string
                nullable: true
              uniqueClicks:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Distinct users who clicked this block.
              totalClicks:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Click events on this block (repeats included).
            required:
              - name
              - blockId
              - tabId
              - tabName
              - uniqueClicks
              - totalClicks
      required:
        - object
        - contentId
        - environmentId
        - startDate
        - endDate
        - timezone
        - contentType
        - uniqueOpens
        - totalOpens
        - uniqueClicks
        - totalClicks
        - byDay
        - blocks
    TrackerAnalyticsDto:
      type: object
      properties:
        object:
          type: string
          enum:
            - contentAnalytics
        contentId:
          type: string
        environmentId:
          type: string
        startDate:
          type: string
        endDate:
          type: string
        timezone:
          type: string
        contentType:
          type: string
          enum:
            - tracker
        uniqueUsers:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Distinct users who fired the tracked event.
        totalOccurrences:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: Occurrences of the tracked event (repeats included).
        byDay:
          type: array
          items:
            type: object
            properties:
              date:
                type: string
                description: ISO date (bucketed in the requested timezone).
              uniqueUsers:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Distinct users who fired the tracked event.
              totalOccurrences:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: Occurrences of the tracked event (repeats included).
            required:
              - date
              - uniqueUsers
              - totalOccurrences
          description: >-
            Per-day activity: each row counts only that calendar day
            (increments, NOT a running total). Summing the `total*` rows
            reproduces the `total*` headline; a `unique*` row is distinct users
            WITHIN THAT DAY, so summing `unique*` rows over-counts a user active
            on several days — there is no daily series for range-wide unique
            users. Note the question-analytics nps/rating byDay uses the
            OPPOSITE convention (rolling-window cumulative).
      required:
        - object
        - contentId
        - environmentId
        - startDate
        - endDate
        - timezone
        - contentType
        - uniqueUsers
        - totalOccurrences
        - byDay
    AnnouncementAnalyticsDto:
      type: object
      properties:
        object:
          type: string
          enum:
            - contentAnalytics
        contentId:
          type: string
        environmentId:
          type: string
        startDate:
          type: string
        endDate:
          type: string
        timezone:
          type: string
        contentType:
          type: string
          enum:
            - announcement
        uniqueSeen:
          type: integer
          minimum: 0
          maximum: 9007199254740991
          description: >-
            Distinct users who saw the announcement (opened the feed listing it,
            or had its popup presented). Seen fires once per (user,
            announcement) — repeat views never add.
        byDay:
          type: array
          items:
            type: object
            properties:
              date:
                type: string
                description: ISO date (bucketed in the requested timezone).
              uniqueSeen:
                type: integer
                minimum: 0
                maximum: 9007199254740991
                description: >-
                  Distinct users who saw the announcement (opened the feed
                  listing it, or had its popup presented). Seen fires once per
                  (user, announcement) — repeat views never add.
            required:
              - date
              - uniqueSeen
          description: >-
            Per-day FIRST-TOUCH activity: each row counts the users whose first
            event of that kind fell on that calendar day. A user appears on
            exactly one day, so rows never double-count and summing them equals
            the range headline. Note the question-analytics nps/rating byDay
            uses a different convention (rolling-window cumulative).
      required:
        - object
        - contentId
        - environmentId
        - startDate
        - endDate
        - timezone
        - contentType
        - uniqueSeen
        - byDay
    ErrorResponseDto:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: >-
                Stable machine-readable code (e.g. E1017). Match on this, never
                on `message`.
            message:
              type: string
              description: Human-readable summary. Wording may change between releases.
            issues:
              description: >-
                Validation errors (E1017) may carry one entry per problem so
                every field can be fixed in a single round-trip. Absent on other
                errors.
              type: array
              items:
                type: object
                properties:
                  rule:
                    type: string
                    description: >-
                      Which validation layer rejected it: schema |
                      reactive_condition | action_not_allowed | step_shape |
                      reference_target | auto_start | media_url. New values may
                      be added; treat an unknown value as a generic validation
                      failure.
                  message:
                    type: string
                  path:
                    description: >-
                      Path into the request body (e.g.
                      `steps[0].triggers[0].when[1]`).
                    type: string
                required:
                  - rule
                  - message
            doc_url:
              type: string
              description: Base URL of the API documentation.
      required:
        - error
  securitySchemes:
    bearer:
      scheme: bearer
      bearerFormat: utp_... personal API token (opaque)
      type: http

````