Ironfang Analytics Heatmaps API

Totals of where visitors click, how far they scroll, how long each part of a page is on screen and where the pointer goes, across the recorded visits to one page. Computed from recordings, so they keep what recordings keep and need analytics.sessions.read. Every figure is per page visit; horizontal positions count from the centre of the viewport.

Operations 4

GET /v1/sites/{siteId}/pages List pages with visits #
GET /v1/sites/{siteId}/pages/changes List the days a page's layout changed #
GET /v1/sites/{siteId}/heatmaps Get a page's heatmap #
GET /v1/sites/{siteId}/heatmaps/compare Compare two periods #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/ironfang:ironfang-analytics-heatmaps-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

ironfang-analytics-heatmaps-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Ironfang Analytics Heatmaps API
  version: 0.1.0
  summary: Sites, origins, public keys and capture settings for session replay and web analytics.
  description: 'Ironfang Analytics follows each visit to your website as a session:

    the pages a visitor saw, in every tab, with how long they stayed, the

    errors and failed requests they met, the events your pages tracked, and

    the recordings that let you replay it, live or afterwards.'
  contact:
    name: Ironfang
    email: hello@ironfang.uk
    url: https://ironfang.com/contact
  termsOfService: https://ironfang.com/legal/terms
  license:
    name: Proprietary - use governed by the Ironfang terms of service
    url: https://ironfang.com/legal/terms
servers:
- url: https://api.ironfang.com/analytics
security:
- apiKey: []
- bearerAuth: []
tags:
- name: Heatmaps
  description: Totals of where visitors click, how far they scroll, how long each part of a page is on screen and where the pointer goes, across the recorded visits to one page. Computed from recordings, so they keep what recordings keep and need analytics.sessions.read. Every figure is per page visit; horizontal positions count from the centre of the viewport.
paths:
  /v1/sites/{siteId}/pages:
    parameters:
    - $ref: '#/components/parameters/SiteId'
    get:
      tags:
      - Heatmaps
      operationId: listHeatmapPages
      summary: List pages with visits
      description: The site's pages that recorded visits showed in a period, most visited first, by device. A recording is indexed shortly after it ends. Needs analytics.sessions.read.
      parameters:
      - $ref: '#/components/parameters/HeatmapFrom'
      - $ref: '#/components/parameters/HeatmapTo'
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 500
          default: 100
      responses:
        '200':
          description: Pages
          content:
            application/json:
              schema:
                type: object
                required:
                - from
                - to
                - pages
                properties:
                  from:
                    type: string
                    format: date-time
                  to:
                    type: string
                    format: date-time
                  pages:
                    type: array
                    items:
                      $ref: '#/components/schemas/HeatmapPage'
        '400':
          $ref: '#/components/responses/InvalidQuery'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/sites/{siteId}/pages/changes:
    parameters:
    - $ref: '#/components/parameters/SiteId'
    get:
      tags:
      - Heatmaps
      operationId: listLayoutChanges
      summary: List the days a page's layout changed
      description: 'Each day whose most common layout differs from the previous day the page was visited: when the page changed, for comparing the week before with the week after. Days are in tz, or the site''s time zone. Needs analytics.sessions.read.'
      parameters:
      - $ref: '#/components/parameters/HeatmapPath'
      - name: bucket
        in: query
        required: false
        description: One device; every device when left out.
        schema:
          $ref: '#/components/schemas/HeatmapBucket'
      - $ref: '#/components/parameters/HeatmapFrom'
      - $ref: '#/components/parameters/HeatmapTo'
      - name: tz
        in: query
        required: false
        description: An IANA time zone for the days.
        schema:
          type: string
          example: Europe/London
      responses:
        '200':
          description: Layout changes
          content:
            application/json:
              schema:
                type: object
                required:
                - path
                - timezone
                - changes
                properties:
                  path:
                    type: string
                  timezone:
                    type: string
                  changes:
                    type: array
                    items:
                      type: object
                      required:
                      - day
                      - from
                      - to
                      properties:
                        day:
                          type: string
                          format: date
                        from:
                          type:
                          - string
                          - 'null'
                        to:
                          type:
                          - string
                          - 'null'
        '400':
          $ref: '#/components/responses/InvalidQuery'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/sites/{siteId}/heatmaps:
    parameters:
    - $ref: '#/components/parameters/SiteId'
    get:
      tags:
      - Heatmaps
      operationId: getHeatmap
      summary: Get a page's heatmap
      description: Attention, scroll reach, clicks and movement for one page and device over a period, from at most 20,000 of its visits (a deterministic sample when there are more), with the visit to draw it over. Fewer than 30 visits is flagged small_sample. Needs analytics.sessions.read.
      parameters:
      - $ref: '#/components/parameters/HeatmapPath'
      - $ref: '#/components/parameters/HeatmapBucketParam'
      - $ref: '#/components/parameters/HeatmapFrom'
      - $ref: '#/components/parameters/HeatmapTo'
      responses:
        '200':
          description: Heatmap
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Heatmap'
        '400':
          $ref: '#/components/responses/InvalidQuery'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/sites/{siteId}/heatmaps/compare:
    parameters:
    - $ref: '#/components/parameters/SiteId'
    get:
      tags:
      - Heatmaps
      operationId: compareHeatmaps
      summary: Compare two periods
      description: One page and device over two periods, with the targets clicked in both and how their rate changed. overlay_valid says both periods have the same most common layout, so a difference overlay on one page means something; across a redesign, show them side by side. Needs analytics.sessions.read.
      parameters:
      - $ref: '#/components/parameters/HeatmapPath'
      - $ref: '#/components/parameters/HeatmapBucketParam'
      - name: a_from
        in: query
        required: true
        schema:
          type: string
          format: date-time
      - name: a_to
        in: query
        required: true
        schema:
          type: string
          format: date-time
      - name: b_from
        in: query
        required: true
        schema:
          type: string
          format: date-time
      - name: b_to
        in: query
        required: true
        schema:
          type: string
          format: date-time
      responses:
        '200':
          description: Comparison
          content:
            application/json:
              schema:
                type: object
                required:
                - a
                - b
                - overlay_valid
                - elements
                properties:
                  a:
                    $ref: '#/components/schemas/Heatmap'
                  b:
                    $ref: '#/components/schemas/Heatmap'
                  overlay_valid:
                    type: boolean
                  elements:
                    type: array
                    items:
                      type: object
                      required:
                      - selector
                      - a
                      - b
                      - change
                      properties:
                        selector:
                          type: string
                        a:
                          type: number
                          description: Clicks per visit in the first period.
                        b:
                          type: number
                          description: Clicks per visit in the second period.
                        change:
                          type: number
        '400':
          $ref: '#/components/responses/InvalidQuery'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  parameters:
    HeatmapPath:
      name: path
      in: query
      required: true
      description: The page's path, without a query string or fragment.
      schema:
        type: string
        example: /pricing
    HeatmapFrom:
      name: from
      in: query
      required: false
      description: The period's start; with to, at most 93 days. Both left out is the seven days to now.
      schema:
        type: string
        format: date-time
    HeatmapBucketParam:
      name: bucket
      in: query
      required: true
      schema:
        $ref: '#/components/schemas/HeatmapBucket'
    SiteId:
      name: siteId
      in: path
      required: true
      schema:
        type: string
        format: uuid
    HeatmapTo:
      name: to
      in: query
      required: false
      description: The period's end, not included.
      schema:
        type: string
        format: date-time
  responses:
    NotFound:
      description: No such object in this organisation (`not_found`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: The credential lacks the permission or scope, names another organisation, or belongs to a partner integration that is not active (`forbidden`, `insufficient_scope`, `integration_inactive`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    InvalidQuery:
      description: An unknown, repeated or malformed query parameter (`invalid_query`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: No credential, an invalid one, an expired partner integration key, or a delegated token where none is accepted (`unauthorized`, `invalid_api_key`, `api_key_expired`, `delegated_not_allowed`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    HeatmapBackground:
      type: object
      required:
      - recording_id
      - epoch_index
      - started_at
      - offset_ms
      - duration_ms
      - layout_hash
      - viewport_width
      - viewport_height
      properties:
        recording_id:
          type: string
          format: uuid
        epoch_index:
          type: integer
        started_at:
          type: string
          format: date-time
        offset_ms:
          type: integer
          description: Where the visit starts in its recording, in milliseconds from the recording's first event, as the replay player counts them.
        duration_ms:
          type: integer
          description: How long the visit lasted.
        layout_hash:
          type:
          - string
          - 'null'
        viewport_width:
          type: integer
        viewport_height:
          type: integer
    Heatmap:
      type: object
      required:
      - path
      - bucket
      - from
      - to
      - visits
      - sampled
      - small_sample
      - visibility_known
      - seconds_on_screen
      - layouts
      - background
      - backgrounds
      - bands
      - clicks
      - moves
      properties:
        path:
          type: string
        bucket:
          $ref: '#/components/schemas/HeatmapBucket'
        from:
          type: string
          format: date-time
        to:
          type: string
          format: date-time
        visits:
          type: integer
          description: Page visits in the period.
        sampled:
          type: integer
          description: The visits the totals come from, at most 20000.
        small_sample:
          type: boolean
          description: Fewer than 30 visits.
        visibility_known:
          type: number
          description: The share of visits whose time excludes a hidden tab (SDK 0.5.0).
        seconds_on_screen:
          type: object
          required:
          - mean
          - median
          properties:
            mean:
              type: number
            median:
              type: number
        layouts:
          type: array
          description: The layouts seen, most common first.
          items:
            type: object
            required:
            - hash
            - visits
            properties:
              hash:
                type:
                - string
                - 'null'
              visits:
                type: integer
        background:
          description: The visit whose page at load the heatmap is drawn over; play it through the playback routes.
          anyOf:
          - $ref: '#/components/schemas/HeatmapBackground'
          - type: 'null'
        backgrounds:
          type: array
          description: 'The visits the heatmap can be drawn over, background first: of the most common layout, at a width near the period''s median, and of those the ones that scrolled furthest. At most 5.'
          items:
            $ref: '#/components/schemas/HeatmapBackground'
        bands:
          type: object
          required:
          - px
          - attention_share
          - ms_per_visit
          - reach
          properties:
            px:
              type: integer
              description: The height of a band.
            attention_share:
              type: array
              items:
                type: number
              description: Per band from the top, the share of a visit's time it was on screen.
            ms_per_visit:
              type: array
              items:
                type: number
            reach:
              type: array
              items:
                type: number
              description: Per band, the share of visits that scrolled to its bottom.
        clicks:
          type: object
          required:
          - per_visit
          - fixed_per_visit
          - cell_px
          - cells
          - fixed_cells
          - elements
          properties:
            per_visit:
              type: number
            fixed_per_visit:
              type: number
              description: Clicks on fixed or sticky elements, which belong to the screen rather than a place on the page.
            cell_px:
              type: integer
            cells:
              type: array
              items:
                $ref: '#/components/schemas/HeatmapCell'
            fixed_cells:
              type: array
              items:
                $ref: '#/components/schemas/HeatmapCell'
            elements:
              type: array
              description: The targets most clicked, named without text.
              items:
                type: object
                required:
                - selector
                - clicks
                - per_visit
                - fixed
                - located
                - offsets
                - cells
                properties:
                  selector:
                    type: string
                  clicks:
                    type: integer
                  per_visit:
                    type: number
                  fixed:
                    type: boolean
                    description: Whether most of its clicks landed on it while fixed or sticky. located, offsets and cells cover those clicks only.
                  located:
                    type: integer
                    description: How many of its clicks carry where within the target they landed (SDK 0.5.0).
                  offsets:
                    type: array
                    description: A sample of the located clicks, where within the target each landed, 0 to 10000 across and down.
                    items:
                      type: array
                      items:
                        type: integer
                      minItems: 2
                      maxItems: 2
                  cells:
                    type: array
                    description: The located clicks in the page grid (the fixed grid when fixed), per visit. Drawing them inside the target's box instead, take these out of cells or fixed_cells so they are not counted twice.
                    items:
                      $ref: '#/components/schemas/HeatmapCell'
        moves:
          type: object
          required:
          - cell_px
          - cells
          properties:
            cell_px:
              type: integer
            cells:
              type: array
              items:
                $ref: '#/components/schemas/HeatmapCell'
              description: Milliseconds per visit the pointer rested in each cell.
    HeatmapBucket:
      type: string
      enum:
      - mobile
      - tablet
      - desktop
      description: By viewport width when the visit began, under 768, under 1280, and wider.
    Error:
      type: object
      required:
      - error
      properties:
        error:
          type: object
          required:
          - code
          - message
          - docs
          properties:
            code:
              type: string
              description: Stable machine-readable code.
            message:
              type: string
              description: Human-readable explanation; do not parse.
            docs:
              type: string
              format: uri
        request_id:
          type: string
    HeatmapPage:
      type: object
      required:
      - path
      - visits
      - mobile
      - tablet
      - desktop
      properties:
        path:
          type: string
        visits:
          type: integer
        mobile:
          type: integer
        tablet:
          type: integer
        desktop:
          type: integer
    HeatmapCell:
      type: array
      description: '[x, y, value]: x cells from the centre of the viewport (negative to the left), y cells from the top of the page (of the viewport for fixed clicks), and the value per visit.'
      items:
        type: number
      minItems: 3
      maxItems: 3
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      bearerFormat: if_live_ platform API key
      description: 'A platform API key minted in the portal. Its scopes are its

        permissions - `analytics:sites:read`, `analytics:sites:write` and the

        other `analytics:` scopes, or `analytics:*` - and it acts only in the

        organisation it was minted for. Keys without the scope a route needs

        are refused with 403.

        '
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Warden JWT
      description: 'A Warden user token. Each route also requires a tenant permission in

        the acting tenant (`X-Ironfang-Tenant`), resolved live from Warden,

        which each operation names: sites need `analytics.sites.read` to read

        and `analytics.sites.write` to change; sessions, recordings and

        heatmaps need `analytics.sessions.read`, and deleting a session or a

        recording `analytics.sessions.delete`. A missing permission is 403; a

        permission lookup failure is 503.

        '
externalDocs:
  description: Ironfang Analytics documentation
  url: https://ironfang.com/analytics/docs