@intlayer/docs 9.0.0-canary.15 → 9.0.0-canary.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/generated/docs.entry.cjs +40 -0
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +40 -0
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/types/generated/docs.entry.d.ts +2 -0
- package/dist/types/generated/docs.entry.d.ts.map +1 -1
- package/docs/ar/cli/index.md +1 -1
- package/docs/ar/configuration.md +42 -1
- package/docs/ar/intlayer_CMS.md +5 -128
- package/docs/ar/live-sync.md +174 -0
- package/docs/ar/releases/v9.md +45 -1
- package/docs/bn/cli/index.md +1 -1
- package/docs/bn/configuration.md +45 -1
- package/docs/cs/cli/index.md +1 -1
- package/docs/cs/configuration.md +45 -1
- package/docs/de/cli/index.md +1 -1
- package/docs/de/configuration.md +42 -1
- package/docs/de/intlayer_CMS.md +5 -135
- package/docs/de/live-sync.md +174 -0
- package/docs/de/releases/v9.md +45 -1
- package/docs/en/analytics.md +222 -0
- package/docs/en/cli/index.md +1 -1
- package/docs/en/configuration.md +42 -1
- package/docs/en/intlayer_CMS.md +6 -140
- package/docs/en/live-sync.md +184 -0
- package/docs/en/releases/v9.md +53 -3
- package/docs/en-GB/cli/index.md +1 -1
- package/docs/en-GB/configuration.md +42 -1
- package/docs/en-GB/intlayer_CMS.md +5 -128
- package/docs/en-GB/live-sync.md +173 -0
- package/docs/en-GB/releases/v9.md +45 -1
- package/docs/es/cli/index.md +1 -1
- package/docs/es/configuration.md +42 -1
- package/docs/es/intlayer_CMS.md +5 -140
- package/docs/es/live-sync.md +176 -0
- package/docs/es/releases/v9.md +45 -1
- package/docs/fr/cli/index.md +1 -1
- package/docs/fr/configuration.md +42 -1
- package/docs/fr/intlayer_CMS.md +5 -135
- package/docs/fr/live-sync.md +174 -0
- package/docs/fr/releases/v9.md +45 -1
- package/docs/hi/cli/index.md +1 -1
- package/docs/hi/configuration.md +42 -1
- package/docs/hi/intlayer_CMS.md +5 -128
- package/docs/hi/live-sync.md +174 -0
- package/docs/hi/releases/v9.md +45 -1
- package/docs/id/cli/index.md +1 -1
- package/docs/id/configuration.md +42 -1
- package/docs/id/intlayer_CMS.md +5 -139
- package/docs/id/live-sync.md +185 -0
- package/docs/id/releases/v9.md +45 -1
- package/docs/it/cli/index.md +1 -1
- package/docs/it/configuration.md +42 -1
- package/docs/it/intlayer_CMS.md +5 -128
- package/docs/it/live-sync.md +174 -0
- package/docs/it/releases/v9.md +45 -1
- package/docs/ja/cli/index.md +1 -1
- package/docs/ja/configuration.md +42 -1
- package/docs/ja/intlayer_CMS.md +5 -139
- package/docs/ja/live-sync.md +185 -0
- package/docs/ja/releases/v9.md +45 -1
- package/docs/ko/cli/index.md +1 -1
- package/docs/ko/configuration.md +42 -1
- package/docs/ko/intlayer_CMS.md +5 -141
- package/docs/ko/live-sync.md +187 -0
- package/docs/ko/releases/v9.md +45 -1
- package/docs/nl/cli/index.md +1 -1
- package/docs/nl/configuration.md +45 -1
- package/docs/pl/cli/index.md +1 -1
- package/docs/pl/configuration.md +45 -1
- package/docs/pl/intlayer_CMS.md +5 -139
- package/docs/pl/live-sync.md +185 -0
- package/docs/pl/releases/v9.md +45 -1
- package/docs/pt/cli/index.md +1 -1
- package/docs/pt/configuration.md +45 -1
- package/docs/pt/intlayer_CMS.md +5 -143
- package/docs/pt/live-sync.md +174 -0
- package/docs/pt/releases/v9.md +45 -1
- package/docs/ru/cli/index.md +1 -1
- package/docs/ru/configuration.md +42 -1
- package/docs/ru/intlayer_CMS.md +5 -139
- package/docs/ru/live-sync.md +185 -0
- package/docs/ru/releases/v9.md +45 -1
- package/docs/tr/cli/index.md +1 -1
- package/docs/tr/configuration.md +42 -1
- package/docs/tr/intlayer_CMS.md +5 -127
- package/docs/tr/live-sync.md +173 -0
- package/docs/tr/releases/v9.md +45 -1
- package/docs/uk/cli/index.md +1 -1
- package/docs/uk/configuration.md +42 -1
- package/docs/uk/intlayer_CMS.md +5 -139
- package/docs/uk/live-sync.md +185 -0
- package/docs/uk/releases/v9.md +45 -1
- package/docs/ur/cli/index.md +1 -1
- package/docs/ur/configuration.md +45 -1
- package/docs/vi/cli/index.md +1 -1
- package/docs/vi/configuration.md +42 -1
- package/docs/vi/intlayer_CMS.md +5 -139
- package/docs/vi/live-sync.md +185 -0
- package/docs/vi/releases/v9.md +45 -1
- package/docs/zh/cli/index.md +1 -1
- package/docs/zh/configuration.md +42 -1
- package/docs/zh/intlayer_CMS.md +5 -129
- package/docs/zh/live-sync.md +175 -0
- package/docs/zh/releases/v9.md +45 -1
- package/package.json +7 -7
- package/src/generated/docs.entry.ts +40 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-07-08
|
|
3
|
+
updatedAt: 2026-07-08
|
|
4
|
+
title: Intlayer Analytics | Track content exposure and run A/B tests
|
|
5
|
+
description: Discover how @intlayer/analytics tracks page/locale views and content exposure, and how to use it to run A/B tests on your Intlayer content.
|
|
6
|
+
keywords:
|
|
7
|
+
- Analytics
|
|
8
|
+
- A/B Testing
|
|
9
|
+
- Audience
|
|
10
|
+
- Internationalization
|
|
11
|
+
- Documentation
|
|
12
|
+
- Intlayer
|
|
13
|
+
- Next.js
|
|
14
|
+
- JavaScript
|
|
15
|
+
- React
|
|
16
|
+
slugs:
|
|
17
|
+
- doc
|
|
18
|
+
- concept
|
|
19
|
+
- analytics
|
|
20
|
+
history:
|
|
21
|
+
- version: 9.0.0
|
|
22
|
+
date: 2026-07-08
|
|
23
|
+
changes: "Init doc — @intlayer/analytics package, provider/node-level tracking, A/B testing, dashboard"
|
|
24
|
+
author: aymericzip
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# Intlayer Analytics Documentation
|
|
28
|
+
|
|
29
|
+
`@intlayer/analytics` is an optional companion package that tells you **which content is actually shown** to your visitors — which page, in which locale, and which specific piece of translated content — so you can understand your audience and run **A/B tests on content**.
|
|
30
|
+
|
|
31
|
+
## Table of Contents
|
|
32
|
+
|
|
33
|
+
<TOC/>
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## What it tracks
|
|
38
|
+
|
|
39
|
+
`@intlayer/analytics` batches three kinds of anonymous events:
|
|
40
|
+
|
|
41
|
+
| Event | Captured where | What it tells you |
|
|
42
|
+
| ------------------ | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
|
43
|
+
| `page_view` | Provider level (`IntlayerProvider`) | Which page and locale a session viewed, on first load, route change, or locale switch. |
|
|
44
|
+
| `content_exposure` | Node level (`useIntlayer` / interpreter plugins) | Which dictionary key / key path was actually resolved and displayed — and, when part of an experiment, which **variant**. |
|
|
45
|
+
| `conversion` | Wherever you call `useConversion()` | A goal reached (signup, click, purchase…) attributed to the A/B variant the session was exposed to. |
|
|
46
|
+
|
|
47
|
+
Events are collected in memory and sent as a **single batched request roughly every 20 seconds** — never on every keystroke or render — so analytics never impacts first render time or adds a request per interaction.
|
|
48
|
+
|
|
49
|
+
## How it powers A/B testing on content
|
|
50
|
+
|
|
51
|
+
Intlayer already lets you declare content [Variants](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dynamic_dictionaries/index.md) (e.g. a `hero-banner` dictionary with a `control` and a `black_friday` variant). `@intlayer/analytics` closes the loop:
|
|
52
|
+
|
|
53
|
+
1. `getVariant(experimentKey, variants)` deterministically assigns each anonymous session to a variant — a pure function of the session id and the experiment key, so the assignment is **stable across the session** and requires **no server round-trip** before first render (no flicker, no layout shift).
|
|
54
|
+
2. Every `content_exposure` event carries the `variant` that was shown.
|
|
55
|
+
3. `useConversion()` lets you attribute a goal (e.g. `"cta_click"`) to that variant.
|
|
56
|
+
4. The dashboard's experiment results endpoint compares conversion rates per variant, including statistical significance (a z-test).
|
|
57
|
+
|
|
58
|
+
## Installation
|
|
59
|
+
|
|
60
|
+
`@intlayer/analytics` is a **peer, optional** dependency — never installed automatically by a framework package. Add it alongside `intlayer`:
|
|
61
|
+
|
|
62
|
+
```bash packageManager="npm"
|
|
63
|
+
npm install @intlayer/analytics
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```bash packageManager="yarn"
|
|
67
|
+
yarn add @intlayer/analytics
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```bash packageManager="pnpm"
|
|
71
|
+
pnpm add @intlayer/analytics
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```bash packageManager="bun"
|
|
75
|
+
bun add @intlayer/analytics
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
If you don't install it, every integration point resolves to a no-op — see [Zero-cost when not installed](#zero-cost-when-not-installed) below.
|
|
79
|
+
|
|
80
|
+
## Configuration
|
|
81
|
+
|
|
82
|
+
Analytics **reuses the existing `editor` configuration block** — there is no separate `analytics` config schema to fill in:
|
|
83
|
+
|
|
84
|
+
```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
|
|
85
|
+
import type { IntlayerConfig } from "intlayer";
|
|
86
|
+
|
|
87
|
+
const config: IntlayerConfig = {
|
|
88
|
+
editor: {
|
|
89
|
+
backendURL: "https://back.intlayer.org", // Also used as the analytics ingestion endpoint
|
|
90
|
+
clientId: "your-client-id", // Also used as the analytics project key
|
|
91
|
+
clientSecret: "your-client-secret",
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export default config;
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
- `editor.backendURL` — the base URL analytics events are sent to (`POST {backendURL}/api/analytics/events`).
|
|
99
|
+
- `editor.clientId` — the public project key attributed to every ingested event. It also acts as the **enable switch**: analytics stays fully disabled (and tree-shaken, see below) until `clientId` is configured.
|
|
100
|
+
|
|
101
|
+
If you self-host Intlayer, analytics automatically points at your own instance since it shares `editor.backendURL`.
|
|
102
|
+
|
|
103
|
+
## Framework support
|
|
104
|
+
|
|
105
|
+
Analytics is wired into the shared `IntlayerProvider` from `react-intlayer`, so it is available today anywhere that provider is used:
|
|
106
|
+
|
|
107
|
+
| Framework | Status |
|
|
108
|
+
| -------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
109
|
+
| React | ✅ Available |
|
|
110
|
+
| Next.js (`next-intlayer`) | ✅ Available (via `react-intlayer`) |
|
|
111
|
+
| React Native / Expo (`react-native-intlayer`) | ✅ Available (via `react-intlayer`) |
|
|
112
|
+
| Vue, Svelte, Angular, Solid, Preact, Lit, Astro, Vanilla | 🚧 Planned — same client, provider-level bindings following the `@intlayer/editor` rollout pattern |
|
|
113
|
+
|
|
114
|
+
## Usage
|
|
115
|
+
|
|
116
|
+
### Automatic provider-level tracking
|
|
117
|
+
|
|
118
|
+
No code changes are required. Once `@intlayer/analytics` is installed and `editor.clientId` is configured, `IntlayerProvider` automatically:
|
|
119
|
+
|
|
120
|
+
- initializes the analytics client on mount,
|
|
121
|
+
- records a `page_view` on initial load,
|
|
122
|
+
- records a `page_view` on every locale change,
|
|
123
|
+
- starts the ~20s flush loop and flushes any remaining events on unmount / tab close (via `navigator.sendBeacon`, falling back to `fetch(..., { keepalive: true })`).
|
|
124
|
+
|
|
125
|
+
### Automatic node-level tracking
|
|
126
|
+
|
|
127
|
+
Every time `useIntlayer` resolves a piece of content for display, the interpreter reports a `content_exposure` event for that exact `dictionaryKey` + key path + locale — again, no code changes required. Repeated exposures of the same node within a flush window are coalesced into a single event with a `count`, so a list re-rendering 50 times doesn't send 50 events.
|
|
128
|
+
|
|
129
|
+
### Tracking conversions for A/B tests
|
|
130
|
+
|
|
131
|
+
Use `useConversion()` to attribute a goal to the variant a session saw:
|
|
132
|
+
|
|
133
|
+
```tsx fileName="CTAButton.tsx" codeFormat="tsx"
|
|
134
|
+
import { useConversion } from "react-intlayer";
|
|
135
|
+
|
|
136
|
+
const CTAButton = () => {
|
|
137
|
+
const trackConversion = useConversion();
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<button
|
|
141
|
+
onClick={() =>
|
|
142
|
+
trackConversion({
|
|
143
|
+
experimentKey: "homepage-hero",
|
|
144
|
+
variant: "black_friday",
|
|
145
|
+
goal: "cta_click",
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
>
|
|
149
|
+
Get started
|
|
150
|
+
</button>
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Resolving a variant client-side
|
|
156
|
+
|
|
157
|
+
```tsx fileName="useHeroVariant.ts" codeFormat="tsx"
|
|
158
|
+
import { getGlobalAnalyticsClient } from "@intlayer/analytics/client";
|
|
159
|
+
|
|
160
|
+
const client = getGlobalAnalyticsClient();
|
|
161
|
+
const variant = client?.getVariant("homepage-hero", [
|
|
162
|
+
"control",
|
|
163
|
+
"black_friday",
|
|
164
|
+
]);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Privacy & performance
|
|
168
|
+
|
|
169
|
+
- **Anonymous by design**: sessions are identified by a rotating id; the backend only ever stores a **SHA-256 hash** of that id — never the raw id, never an IP address.
|
|
170
|
+
- **Location is coarse**: only a country code, derived from CDN geolocation headers (`cf-ipcountry`, `x-vercel-ip-country`, …) — no IP is read or stored.
|
|
171
|
+
- **URLs exclude search params** by default, so query strings are never captured.
|
|
172
|
+
- **Sampling**: `sampleRate` lets you keep only a fraction of content-exposure events on high-traffic apps.
|
|
173
|
+
- **Batched**: one request roughly every 20 seconds (`flushInterval`), or earlier if the buffer fills up (`maxBufferSize`) — never one request per event.
|
|
174
|
+
|
|
175
|
+
### Zero-cost when not installed
|
|
176
|
+
|
|
177
|
+
`@intlayer/analytics` follows the exact same optional-dependency pattern as `@intlayer/editor`:
|
|
178
|
+
|
|
179
|
+
- every integration point loads the package via a **dynamic `import()` wrapped in `try/catch`** — an app that never installs `@intlayer/analytics` never pays a bundle-size or runtime cost, and never sees an error;
|
|
180
|
+
- a compile-time env var (`INTLAYER_ANALYTICS_ENABLED`), automatically set to `'false'` by `@intlayer/config` whenever `editor.clientId` is not configured, lets bundlers **dead-code-eliminate** the whole integration;
|
|
181
|
+
- analytics is disabled inside the Intlayer editor/CMS preview iframe, so editor sessions are never counted as real traffic.
|
|
182
|
+
|
|
183
|
+
## Dashboard: Analytics page
|
|
184
|
+
|
|
185
|
+
Once your project has collected events, the **Analytics** page in the [Intlayer dashboard](https://app.intlayer.org/analytics) (visible in the sidebar once a project is selected) shows:
|
|
186
|
+
|
|
187
|
+
- **Active users** — distinct visitors over the selected rolling window (7 / 30 / 90 days).
|
|
188
|
+
- **Users today** and **users over the last 7 days**.
|
|
189
|
+
- **Page views** over the selected window.
|
|
190
|
+
- An **evolution graph** of daily distinct visitors.
|
|
191
|
+
- **Locales** and **Location** breakdown tabs, ranking your audience by locale and by country.
|
|
192
|
+
|
|
193
|
+
## Backend API reference
|
|
194
|
+
|
|
195
|
+
All read endpoints require authentication; ingestion is public and attributed by `clientId`.
|
|
196
|
+
|
|
197
|
+
| Method | Endpoint | Description |
|
|
198
|
+
| ------ | ------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
199
|
+
| `POST` | `/api/analytics/events` | Ingest a batch of events (public, attributed by `clientId` in the body). |
|
|
200
|
+
| `GET` | `/api/analytics/overview` | Page/locale totals for the authenticated project. |
|
|
201
|
+
| `GET` | `/api/analytics/audience?days=30` | Distinct visitors, page views, daily series, locale + country breakdowns. |
|
|
202
|
+
| `GET` | `/api/analytics/content-stats` | Per-content exposure totals, grouped by dictionary key / key path / locale. |
|
|
203
|
+
| `GET` | `/api/analytics/experiments/:experimentKey` | Per-variant conversion rates and statistical significance for an A/B experiment. |
|
|
204
|
+
|
|
205
|
+
You can also call these programmatically with the [CMS SDK](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md):
|
|
206
|
+
|
|
207
|
+
```ts fileName="analytics.ts"
|
|
208
|
+
import { createIntlayerCMS } from "@intlayer/api";
|
|
209
|
+
import { analyticsEndpoint } from "@intlayer/api/analytics";
|
|
210
|
+
|
|
211
|
+
const cms = createIntlayerCMS();
|
|
212
|
+
|
|
213
|
+
const { data: audience } = await analyticsEndpoint(cms).getAudience(30);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Useful links
|
|
217
|
+
|
|
218
|
+
- [Dynamic Dictionaries - Collections & Variants](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dynamic_dictionaries/index.md)
|
|
219
|
+
- [Intlayer CMS - CMS SDK](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md)
|
|
220
|
+
- [Intlayer Visual Editor](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_visual_editor.md)
|
|
221
|
+
- [Configuration Reference](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/configuration.md)
|
|
222
|
+
- [Self-Hosting Guide](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/self_hosting.md)
|
package/docs/en/cli/index.md
CHANGED
|
@@ -125,7 +125,7 @@ To see how to configure available locales, or other parameters, refer to the [co
|
|
|
125
125
|
|
|
126
126
|
### Authentication
|
|
127
127
|
|
|
128
|
-
- **[Login](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/login.md)** - Authenticate with the Intlayer CMS and get access credentials
|
|
128
|
+
- **[Login](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/cli/login.md)** - Authenticate with the Intlayer CMS and get access credentials
|
|
129
129
|
|
|
130
130
|
### Core Commands
|
|
131
131
|
|
package/docs/en/configuration.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2024-08-13
|
|
3
|
-
updatedAt: 2026-
|
|
3
|
+
updatedAt: 2026-07-11
|
|
4
4
|
title: Configuration
|
|
5
5
|
description: Learn how to configure Intlayer for your application. Understand the various settings and options available to customize Intlayer to your needs.
|
|
6
6
|
keywords:
|
|
@@ -14,6 +14,9 @@ slugs:
|
|
|
14
14
|
- concept
|
|
15
15
|
- configuration
|
|
16
16
|
history:
|
|
17
|
+
- version: 9.0.0
|
|
18
|
+
date: 2026-07-11
|
|
19
|
+
changes: "Add `analytics` configuration"
|
|
17
20
|
- version: 9.0.0
|
|
18
21
|
date: 2026-06-24
|
|
19
22
|
changes: "Add `enableProxy` option to the routing configuration"
|
|
@@ -365,6 +368,30 @@ const config: IntlayerConfig = {
|
|
|
365
368
|
liveSync: true,
|
|
366
369
|
},
|
|
367
370
|
|
|
371
|
+
/**
|
|
372
|
+
* Analytics configuration.
|
|
373
|
+
*/
|
|
374
|
+
analytics: {
|
|
375
|
+
/**
|
|
376
|
+
* Whether analytics collection is enabled (page views, content exposures, A/B events).
|
|
377
|
+
* Requires `editor.clientId` to be set for attribution.
|
|
378
|
+
* Default: false
|
|
379
|
+
*/
|
|
380
|
+
enabled: true,
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Milliseconds between automatic batched flushes to the backend.
|
|
384
|
+
* Default: 20000
|
|
385
|
+
*/
|
|
386
|
+
flushInterval: 20000,
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Fraction of sessions to record, from 0 (none) to 1 (all).
|
|
390
|
+
* Default: 1
|
|
391
|
+
*/
|
|
392
|
+
sampleRate: 1,
|
|
393
|
+
},
|
|
394
|
+
|
|
368
395
|
/**
|
|
369
396
|
* AI-powered translation and generation settings.
|
|
370
397
|
*/
|
|
@@ -680,6 +707,20 @@ Defines settings related to the integrated editor, including server port and act
|
|
|
680
707
|
| `liveSyncPort` | The port of the live sync server. | `number` | `4000` | `4000` | |
|
|
681
708
|
| `liveSyncURL` | The URL of the live sync server. | `string` | `'http://localhost:{liveSyncPort}'` | `'https://example.com'` | Points to localhost by default; can be changed for a remote live sync server. |
|
|
682
709
|
|
|
710
|
+
### Analytics Configuration
|
|
711
|
+
|
|
712
|
+
Defines settings related to Intlayer analytics: collecting which content is actually shown to users (page views, content exposures) and powering content A/B testing.
|
|
713
|
+
|
|
714
|
+
Analytics is strictly opt-in: nothing is collected unless `analytics.enabled` is explicitly set to `true` **and** a project key (`editor.clientId`) is configured for attribution. When disabled (the default), the whole analytics integration is dead-code-eliminated from your application bundle.
|
|
715
|
+
|
|
716
|
+
| Field | Description | Type | Default | Example | Note |
|
|
717
|
+
| --------------- | ------------------------------------------------------------------------- | --------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
718
|
+
| `enabled` | Enables analytics collection (page views, content exposures, A/B events). | `boolean` | `false` | `true` | Requires `editor.clientId` to be set for attribution; otherwise analytics stays disabled even if `enabled` is `true`. |
|
|
719
|
+
| `flushInterval` | Milliseconds between automatic batched flushes to the backend. | `number` | `20000` | `10000` | |
|
|
720
|
+
| `sampleRate` | Fraction of sessions to record, from `0` (none) to `1` (all). | `number` | `1` | `0.5` | Sampling is deterministic per session, so a recorded session reports all of its events (no partial funnels). |
|
|
721
|
+
|
|
722
|
+
---
|
|
723
|
+
|
|
683
724
|
### Routing Configuration
|
|
684
725
|
|
|
685
726
|
Settings that control routing behavior, including URL structure, locale storage, and middleware handling.
|
package/docs/en/intlayer_CMS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-08-23
|
|
3
|
-
updatedAt: 2026-
|
|
3
|
+
updatedAt: 2026-07-08
|
|
4
4
|
title: Intlayer CMS | Externalize your content into the Intlayer CMS
|
|
5
5
|
description: Externalize your content into the Intlayer CMS to delegate the management of your content to your team.
|
|
6
6
|
keywords:
|
|
@@ -18,6 +18,9 @@ slugs:
|
|
|
18
18
|
- cms
|
|
19
19
|
youtubeVideo: https://www.youtube.com/watch?v=UDDTnirwi_4
|
|
20
20
|
history:
|
|
21
|
+
- version: 9.0.0
|
|
22
|
+
date: 2026-07-08
|
|
23
|
+
changes: "Move Live Sync section to its own page (live-sync.md), keep a short intro + link here"
|
|
21
24
|
- version: 9.0.0
|
|
22
25
|
date: 2026-06-30
|
|
23
26
|
changes: "Add Self-Hosting section: Docker Compose bootstrap, service inventory, SDK configuration, optional features, and upgrade notes"
|
|
@@ -401,146 +404,9 @@ await pushDictionaries([{ key: "home", content: { title: "Home" } }]);
|
|
|
401
404
|
|
|
402
405
|
## Live sync
|
|
403
406
|
|
|
404
|
-
Live Sync lets your app reflect CMS content changes at runtime
|
|
405
|
-
|
|
406
|
-
Enable Live Sync by updating your Intlayer configuration:
|
|
407
|
-
|
|
408
|
-
```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
|
|
409
|
-
import type { IntlayerConfig } from "intlayer";
|
|
410
|
-
|
|
411
|
-
const config: IntlayerConfig = {
|
|
412
|
-
// ... other configuration settings
|
|
413
|
-
editor: {
|
|
414
|
-
/**
|
|
415
|
-
* Enables hot reloading of locale configurations when changes are detected.
|
|
416
|
-
* For example, when a dictionary is added or updated, the application updates
|
|
417
|
-
* the content displayed on the page.
|
|
418
|
-
*
|
|
419
|
-
* Because hot reloading requires a continuous connection to the server, it is
|
|
420
|
-
* only available for clients of the `enterprise` plan.
|
|
421
|
-
*
|
|
422
|
-
* Default: false
|
|
423
|
-
*/
|
|
424
|
-
liveSync: true,
|
|
425
|
-
},
|
|
426
|
-
dictionary: {
|
|
427
|
-
/**
|
|
428
|
-
* Controls how dictionaries are imported:
|
|
429
|
-
*
|
|
430
|
-
* - "fetch": Dictionaries are fetched dynamically using the Live Sync API.
|
|
431
|
-
* Replaces useIntlayer with useDictionaryDynamic.
|
|
432
|
-
*
|
|
433
|
-
* Note: Live mode uses the Live Sync API to fetch dictionaries. If the API call
|
|
434
|
-
* fails, dictionaries are imported dynamically.
|
|
435
|
-
* Note: Only dictionaries with remote content and "live" flags use live mode.
|
|
436
|
-
* Others use dynamic mode for performance.
|
|
437
|
-
*/
|
|
438
|
-
importMode: "fetch",
|
|
439
|
-
},
|
|
440
|
-
};
|
|
441
|
-
|
|
442
|
-
export default config;
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
Start the Live Sync server to wrap your application:
|
|
446
|
-
|
|
447
|
-
Example using standalone server:
|
|
448
|
-
|
|
449
|
-
```json5 fileName="package.json"
|
|
450
|
-
{
|
|
451
|
-
"scripts": {
|
|
452
|
-
// ... other scripts
|
|
453
|
-
"live:start": "npx intlayer live",
|
|
454
|
-
},
|
|
455
|
-
}
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
You can also use your application server in parallel using the `--process` argument.
|
|
459
|
-
|
|
460
|
-
Example using Next.js:
|
|
461
|
-
|
|
462
|
-
```json5 fileName="package.json"
|
|
463
|
-
{
|
|
464
|
-
"scripts": {
|
|
465
|
-
// ... other scripts
|
|
466
|
-
"build": "next build",
|
|
467
|
-
"dev": "next dev",
|
|
468
|
-
"start": "npx intlayer live --with 'next start'",
|
|
469
|
-
},
|
|
470
|
-
}
|
|
471
|
-
```
|
|
472
|
-
|
|
473
|
-
Example using Vite:
|
|
474
|
-
|
|
475
|
-
```json5 fileName="package.json"
|
|
476
|
-
{
|
|
477
|
-
"scripts": {
|
|
478
|
-
// ... other scripts
|
|
479
|
-
"build": "vite build",
|
|
480
|
-
"dev": "vite dev",
|
|
481
|
-
"start": "npx intlayer live --with 'vite start'",
|
|
482
|
-
},
|
|
483
|
-
}
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
The Live Sync server wraps your application and automatically applies updated content as it arrives.
|
|
487
|
-
|
|
488
|
-
To receive change notifications from the CMS, the Live Sync server maintains an SSE connection to the backend. When content changes in the CMS, the backend forwards the update to the Live Sync server, which writes the new dictionaries. Your application will reflect the update on the next navigation or browser reload, no rebuild required.
|
|
489
|
-
|
|
490
|
-
Flow chart (CMS/Backend -> Live Sync Server -> Application Server -> Frontend):
|
|
491
|
-
|
|
492
|
-

|
|
493
|
-
|
|
494
|
-
How it works:
|
|
495
|
-
|
|
496
|
-

|
|
497
|
-
|
|
498
|
-
### Development workflow (local)
|
|
499
|
-
|
|
500
|
-
- In development, all remote dictionaries are fetched when the application starts, so you can test updates quickly.
|
|
501
|
-
- To test Live Sync locally with Next.js, wrap your dev server:
|
|
502
|
-
|
|
503
|
-
```json5 fileName="package.json"
|
|
504
|
-
{
|
|
505
|
-
"scripts": {
|
|
506
|
-
// ... other scripts
|
|
507
|
-
"dev": "npx intlayer live --with 'next dev'",
|
|
508
|
-
// "dev": "npx intlayer live --with 'vite dev'", // For Vite
|
|
509
|
-
},
|
|
510
|
-
}
|
|
511
|
-
```
|
|
512
|
-
|
|
513
|
-
Enable optimization so Intlayer applies the Live import transformations during development:
|
|
514
|
-
|
|
515
|
-
```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
|
|
516
|
-
import type { IntlayerConfig } from "intlayer";
|
|
517
|
-
|
|
518
|
-
const config: IntlayerConfig = {
|
|
519
|
-
editor: {
|
|
520
|
-
applicationURL: "http://localhost:5173",
|
|
521
|
-
liveSyncURL: "http://localhost:4000",
|
|
522
|
-
liveSync: true,
|
|
523
|
-
},
|
|
524
|
-
dictionary: {
|
|
525
|
-
importMode: "fetch",
|
|
526
|
-
},
|
|
527
|
-
build: {
|
|
528
|
-
optimize: true, // default: process.env.NODE_ENV === 'production'
|
|
529
|
-
},
|
|
530
|
-
};
|
|
531
|
-
|
|
532
|
-
export default config;
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
This setup wraps your dev server with the Live Sync server, fetches remote dictionaries at startup, and streams updates from the CMS via SSE. Refresh the page to see changes.
|
|
536
|
-
|
|
537
|
-
Notes and constraints:
|
|
407
|
+
Live Sync lets your app reflect CMS content changes at runtime — no rebuild or redeploy required. When enabled, updates are streamed to a Live Sync server that refreshes the dictionaries your application reads.
|
|
538
408
|
|
|
539
|
-
|
|
540
|
-
- Live Sync does not work with static output. For Next.js, the page must be dynamic to receive updates at runtime (e.g., use `generateStaticParams`, `generateMetadata`, `getServerSideProps`, or `getStaticProps` appropriately to avoid full static-only constraints).
|
|
541
|
-
- In the CMS, each dictionary has a `live` flag. Only dictionaries with `live=true` are fetched via the live sync API; others are imported dynamically and remain unchanged at runtime.
|
|
542
|
-
- The `live` flag is evaluated for each dictionary at build time. If remote content wasn't flagged `live=true` during build, you must rebuild to enable Live Sync for that dictionary.
|
|
543
|
-
- The live sync server must be able to write to `.intlayer`. In containers, ensure write access to `/.intlayer`.
|
|
409
|
+
For the full setup guide (configuration, starting the Live Sync server, the local development workflow, and constraints), see the [Live Sync documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/live-sync.md).
|
|
544
410
|
|
|
545
411
|
## Self-Hosting
|
|
546
412
|
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-07-08
|
|
3
|
+
updatedAt: 2026-07-08
|
|
4
|
+
title: Live Sync | Reflect CMS content changes at runtime
|
|
5
|
+
description: Let your app reflect Intlayer CMS content changes at runtime, with no rebuild or redeploy required.
|
|
6
|
+
keywords:
|
|
7
|
+
- Live Sync
|
|
8
|
+
- CMS
|
|
9
|
+
- Visual Editor
|
|
10
|
+
- Internationalization
|
|
11
|
+
- Documentation
|
|
12
|
+
- Intlayer
|
|
13
|
+
- Next.js
|
|
14
|
+
- Vite
|
|
15
|
+
history:
|
|
16
|
+
- version: 9.0.0
|
|
17
|
+
date: 2026-07-08
|
|
18
|
+
changes: "Extracted from the Intlayer CMS documentation into its own page"
|
|
19
|
+
- version: 6.0.1
|
|
20
|
+
date: 2025-09-22
|
|
21
|
+
changes: "Add live sync documentation"
|
|
22
|
+
- version: 6.0.0
|
|
23
|
+
date: 2025-09-04
|
|
24
|
+
changes: "Replace `hotReload` field by `liveSync`"
|
|
25
|
+
author: aymericzip
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
# Intlayer Live Sync
|
|
29
|
+
|
|
30
|
+
Live Sync lets your app reflect [Intlayer CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md) content changes at runtime. No rebuild or redeploy required. When enabled, updates are streamed to a Live Sync server that refreshes the dictionaries your application reads.
|
|
31
|
+
|
|
32
|
+
## Table of Contents
|
|
33
|
+
|
|
34
|
+
<TOC/>
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Enabling Live Sync
|
|
39
|
+
|
|
40
|
+
Enable Live Sync by updating your Intlayer configuration:
|
|
41
|
+
|
|
42
|
+
```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
|
|
43
|
+
import type { IntlayerConfig } from "intlayer";
|
|
44
|
+
|
|
45
|
+
const config: IntlayerConfig = {
|
|
46
|
+
// ... other configuration settings
|
|
47
|
+
editor: {
|
|
48
|
+
/**
|
|
49
|
+
* Enables hot reloading of locale configurations when changes are detected.
|
|
50
|
+
* For example, when a dictionary is added or updated, the application updates
|
|
51
|
+
* the content displayed on the page.
|
|
52
|
+
*
|
|
53
|
+
* Because hot reloading requires a continuous connection to the server, it is
|
|
54
|
+
* only available for clients of the `enterprise` plan.
|
|
55
|
+
*
|
|
56
|
+
* Default: false
|
|
57
|
+
*/
|
|
58
|
+
liveSync: true,
|
|
59
|
+
},
|
|
60
|
+
dictionary: {
|
|
61
|
+
/**
|
|
62
|
+
* Controls how dictionaries are imported:
|
|
63
|
+
*
|
|
64
|
+
* - "fetch": Dictionaries are fetched dynamically using the Live Sync API.
|
|
65
|
+
* Replaces useIntlayer with useDictionaryDynamic.
|
|
66
|
+
*
|
|
67
|
+
* Note: Live mode uses the Live Sync API to fetch dictionaries. If the API call
|
|
68
|
+
* fails, dictionaries are imported dynamically.
|
|
69
|
+
* Note: Only dictionaries with remote content and "live" flags use live mode.
|
|
70
|
+
* Others use dynamic mode for performance.
|
|
71
|
+
*/
|
|
72
|
+
importMode: "fetch",
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export default config;
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Start the Live Sync server to wrap your application:
|
|
80
|
+
|
|
81
|
+
Example using standalone server:
|
|
82
|
+
|
|
83
|
+
```json5 fileName="package.json"
|
|
84
|
+
{
|
|
85
|
+
"scripts": {
|
|
86
|
+
// ... other scripts
|
|
87
|
+
"live:start": "npx intlayer live",
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
You can also use your application server in parallel using the `--process` argument.
|
|
93
|
+
|
|
94
|
+
Example using Next.js:
|
|
95
|
+
|
|
96
|
+
```json5 fileName="package.json"
|
|
97
|
+
{
|
|
98
|
+
"scripts": {
|
|
99
|
+
// ... other scripts
|
|
100
|
+
"build": "next build",
|
|
101
|
+
"dev": "next dev",
|
|
102
|
+
"start": "npx intlayer live --with 'next start'",
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Example using Vite:
|
|
108
|
+
|
|
109
|
+
```json5 fileName="package.json"
|
|
110
|
+
{
|
|
111
|
+
"scripts": {
|
|
112
|
+
// ... other scripts
|
|
113
|
+
"build": "vite build",
|
|
114
|
+
"dev": "vite dev",
|
|
115
|
+
"start": "npx intlayer live --with 'vite start'",
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The Live Sync server wraps your application and automatically applies updated content as it arrives.
|
|
121
|
+
|
|
122
|
+
To receive change notifications from the CMS, the Live Sync server maintains an SSE connection to the backend. When content changes in the CMS, the backend forwards the update to the Live Sync server, which writes the new dictionaries. Your application will reflect the update on the next navigation or browser reload, no rebuild required.
|
|
123
|
+
|
|
124
|
+
Flow chart (CMS/Backend -> Live Sync Server -> Application Server -> Frontend):
|
|
125
|
+
|
|
126
|
+

|
|
127
|
+
|
|
128
|
+
How it works:
|
|
129
|
+
|
|
130
|
+

|
|
131
|
+
|
|
132
|
+
## Development workflow (local)
|
|
133
|
+
|
|
134
|
+
- In development, all remote dictionaries are fetched when the application starts, so you can test updates quickly.
|
|
135
|
+
- To test Live Sync locally with Next.js, wrap your dev server:
|
|
136
|
+
|
|
137
|
+
```json5 fileName="package.json"
|
|
138
|
+
{
|
|
139
|
+
"scripts": {
|
|
140
|
+
// ... other scripts
|
|
141
|
+
"dev": "npx intlayer live --with 'next dev'",
|
|
142
|
+
// "dev": "npx intlayer live --with 'vite dev'", // For Vite
|
|
143
|
+
},
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Enable optimization so Intlayer applies the Live import transformations during development:
|
|
148
|
+
|
|
149
|
+
```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
|
|
150
|
+
import type { IntlayerConfig } from "intlayer";
|
|
151
|
+
|
|
152
|
+
const config: IntlayerConfig = {
|
|
153
|
+
editor: {
|
|
154
|
+
applicationURL: "http://localhost:5173",
|
|
155
|
+
liveSyncURL: "http://localhost:4000",
|
|
156
|
+
liveSync: true,
|
|
157
|
+
},
|
|
158
|
+
dictionary: {
|
|
159
|
+
importMode: "fetch",
|
|
160
|
+
},
|
|
161
|
+
build: {
|
|
162
|
+
optimize: true, // default: process.env.NODE_ENV === 'production'
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export default config;
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
This setup wraps your dev server with the Live Sync server, fetches remote dictionaries at startup, and streams updates from the CMS via SSE. Refresh the page to see changes.
|
|
170
|
+
|
|
171
|
+
## Notes and constraints
|
|
172
|
+
|
|
173
|
+
- Add the live sync origin to your site security policy (CSP). Ensure the live sync URL is allowed in `connect-src` (and `frame-ancestors` if relevant).
|
|
174
|
+
- Live Sync does not work with static output. For Next.js, the page must be dynamic to receive updates at runtime (e.g., use `generateStaticParams`, `generateMetadata`, `getServerSideProps`, or `getStaticProps` appropriately to avoid full static-only constraints).
|
|
175
|
+
- In the CMS, each dictionary has a `live` flag. Only dictionaries with `live=true` are fetched via the live sync API; others are imported dynamically and remain unchanged at runtime.
|
|
176
|
+
- The `live` flag is evaluated for each dictionary at build time. If remote content wasn't flagged `live=true` during build, you must rebuild to enable Live Sync for that dictionary.
|
|
177
|
+
- The live sync server must be able to write to `.intlayer`. In containers, ensure write access to `/.intlayer`.
|
|
178
|
+
|
|
179
|
+
## Useful links
|
|
180
|
+
|
|
181
|
+
- [Intlayer CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md)
|
|
182
|
+
- [Intlayer Visual Editor](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_visual_editor.md)
|
|
183
|
+
- [Configuration Reference](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/configuration.md)
|
|
184
|
+
- [Self-Hosting Guide](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/self_hosting.md)
|