> For the complete Lynkow documentation index in agent-friendly format, see [llms.txt](/llms.txt).

# Collect an analytics event

**Publié le** : 2026-07-04
**Catégorie** : Analytics & Tracking

## `POST /analytics/events`

**Collect an analytics event**

Ingest one analytics event. The endpoint is fire-and-forget: it
always responds 204 No Content with an empty body, whether the event
was recorded or silently dropped (validation error, excluded IP,
excluded path, tracking disabled on the site, or a localhost origin).
This is by design to avoid client-side error noise. The body field
set follows the `collectAnalyticsValidator` schema (event name, page
path, optional properties).

### Request Body

Content-Type: `application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `session_id` | string | Yes | Required. Analytics session UUID |
| `visitor_id` | string | Yes | Required. 8-64 characters |
| `cookie_visitor_id` | string \| null | No | Visitor UUID from the consent cookie (set when consent is given) |
| `visitor_id_source` | "cookie" \| "fingerprint" \| "hybrid" | No | One of: cookie, fingerprint, hybrid |
| `event_type` | "pageview" \| "scroll" \| "time_on_page" \| "cwv" \| "exit" \| "heartbeat" \| "click" \| "outbound_link" \| "file_download" \| "email_click" \| "phone_click" \| "rage_click" \| "dead_click" \| "copy" \| "form_start" \| "form_submit" \| "form_abandon" \| "form_field" \| "form_error" \| "heatmap_click" | Yes | Required. One of: pageview, scroll, time_on_page, cwv, exit, heartbeat, click, outbound_link, file_download, email_click, phone_click, rage_click, dead_click, copy, form_start, form_submit, form_abandon, form_field, form_error, heatmap_click |
| `page_url` | string | No | Max 2048 characters |
| `page_path` | string | Yes | Required. Max 1024 characters |
| `event_time` | string | Yes | Required |
| `page_title` | string | No | Max 500 characters |
| `page_referrer` | string \| null | No | URL of the referring page |
| `scroll_depth` | number \| null | No | Scroll depth as a percentage (0-100) |
| `time_on_page` | number \| null | No | Time on page in milliseconds (max 3600000) |
| `engaged_time` | number \| null | No | Active engagement time in milliseconds (max 3600000) |
| `lcp` | number \| null | No | Largest Contentful Paint in milliseconds (Core Web Vital) |
| `fid` | number \| null | No | First Input Delay in milliseconds (Core Web Vital) |
| `cls` | number \| null | No | Cumulative Layout Shift score (unitless, Core Web Vital) |
| `ttfb` | number \| null | No | Time To First Byte in milliseconds |
| `inp` | number \| null | No | Interaction to Next Paint in milliseconds (Core Web Vital) |
| `utm_source` | string \| null | No | UTM source campaign parameter |
| `utm_medium` | string \| null | No | UTM medium campaign parameter |
| `utm_campaign` | string \| null | No | UTM campaign name parameter |
| `utm_term` | string \| null | No | UTM term campaign parameter |
| `utm_content` | string \| null | No | UTM content campaign parameter |
| `traffic_source` | "direct" \| "organic" \| "social" \| "paid" \| "referral" \| "email" \| "internal" \| "ai" \| null | No | Traffic source channel: direct, organic, social, paid, referral, email, internal, ai |
| `device_type` | "desktop" \| "laptop" \| "mobile" \| "tablet" \| null | No | Device category: desktop, laptop, mobile, tablet |
| `browser` | string \| null | No | Browser name |
| `browser_version` | string \| null | No | Browser version string |
| `os` | string \| null | No | Operating system name |
| `os_version` | string \| null | No | Operating system version string |
| `screen_width` | number \| null | No | Screen width in pixels |
| `screen_height` | number \| null | No | Screen height in pixels |
| `language` | string \| null | No | Browser language code |
| `timezone` | string \| null | No | Timezone name (IANA, e.g. Europe/Paris) |
| `referrer_domain` | string \| null | No | Domain of the referrer |
| `is_entry` | boolean | No | Boolean |
| `is_exit` | boolean | No | Boolean |
| `visible` | boolean | No | Boolean |
| `max_scroll_depth` | number \| null | No | Maximum scroll depth reached as a percentage (0-100) |
| `click_x` | number \| null | No | Horizontal click coordinate in pixels |
| `click_y` | number \| null | No | Vertical click coordinate in pixels |
| `click_element` | string \| null | No | Descriptor of the clicked element |
| `click_element_tag` | string \| null | No | Tag name of the clicked element |
| `click_element_id` | string \| null | No | ID attribute of the clicked element |
| `click_element_class` | string \| null | No | Class attribute of the clicked element |
| `click_element_text` | string \| null | No | Text content of the clicked element |
| `click_target_url` | string \| null | No | Target URL of the clicked link |
| `click_count` | number \| null | No | Number of clicks recorded for the event |
| `viewport_width` | number \| null | No | Viewport width in pixels |
| `viewport_height` | number \| null | No | Viewport height in pixels |
| `file_name` | string \| null | No | Name of the downloaded file |
| `file_extension` | string \| null | No | Extension of the downloaded file |
| `file_url` | string \| null | No | URL of the downloaded file |
| `copied_text` | string \| null | No | Text copied by the visitor (copy event) |
| `scroll_behavior` | "reading" \| "skimming" \| "jumping" \| null | No | Scroll behavior pattern: reading, skimming, jumping |
| `form_id` | string \| null | No | Identifier of the form involved in the event |
| `form_name` | string \| null | No | Name of the form involved in the event |
| `field_name` | string \| null | No | Name of the form field involved in the event |
| `field_type` | string \| null | No | Type of the form field involved in the event |
| `field_time` | number \| null | No | Time spent on the form field in milliseconds |
| `error_message` | string \| null | No | Form validation or submission error message |
| `form_completion_rate` | number \| null | No | Form completion rate as a percentage (0-100) |


### Responses

| Status | Description |
| --- | --- |
| `204` | No content |
| `422` | Validation error |


> **Notes:** Returns HTTP 204 No Content in all cases (success and every
> silent-drop branch); the response body is empty, so clients should
> not parse it. Rate-limit bucket: analytics (~1200 rpm per IP).

### Examples

```curl
curl -X POST "https://api.lynkow.com/storefront/{siteId}/analytics/events" \
  -H "Content-Type: application/json" \
  -d '{ "event": "page_view", "path": "/pricing" }'
```

```javascript
navigator.sendBeacon(
  `https://api.lynkow.com/storefront/${siteId}/analytics/events`,
  JSON.stringify({ event: 'page_view', path: '/pricing' })
)
```

---