|
| 1 | +--- |
| 2 | +title: Telemetry |
| 3 | +sidebarTitle: Telemetry |
| 4 | +keywords: "telemetry, analytics, usage tracking, billing, license key, document tracking" |
| 5 | +--- |
| 6 | + |
| 7 | +SuperDoc collects lightweight telemetry to track document opens for usage-based billing. Telemetry is enabled by default and runs silently in the background — it never blocks rendering or breaks your app. |
| 8 | + |
| 9 | +## What gets collected |
| 10 | + |
| 11 | +Each time a document is opened or imported, SuperDoc sends a single event containing: |
| 12 | + |
| 13 | +| Field | Description | Example | |
| 14 | +|-------|-------------|---------| |
| 15 | +| `documentId` | A hashed document identifier (not the content itself) | `a1b2c3d4...` | |
| 16 | +| `documentCreatedAt` | The document's original creation timestamp | `2024-01-15T10:30:00Z` | |
| 17 | +| `superdocVersion` | The version of the SuperDoc library | `1.15.0` | |
| 18 | +| `browserInfo` | User agent, hostname, and screen size | `{ hostname: "app.example.com", ... }` | |
| 19 | +| `metadata` | Custom key-value pairs you optionally provide | `{ customerId: "123" }` | |
| 20 | + |
| 21 | +SuperDoc does **not** collect: |
| 22 | +- Document content or text |
| 23 | +- User identities or personal data |
| 24 | +- Keystrokes, edits, or change history |
| 25 | +- Cookies or session tokens (`credentials: 'omit'`) |
| 26 | + |
| 27 | +## How it works |
| 28 | + |
| 29 | +1. You open or import a document |
| 30 | +2. SuperDoc generates a **document identifier** — a CRC32 hash derived from the file's metadata (not its content) |
| 31 | +3. A single `POST` request fires to the telemetry endpoint |
| 32 | +4. If the request fails (network error, blocked by firewall), it fails silently |
| 33 | + |
| 34 | +``` |
| 35 | +Document opened → Generate identifier hash → POST to endpoint → Done |
| 36 | +``` |
| 37 | + |
| 38 | +<Note> |
| 39 | +The telemetry request is non-blocking and fire-and-forget. Your editor loads regardless of the outcome. |
| 40 | +</Note> |
| 41 | + |
| 42 | +## Configuration |
| 43 | + |
| 44 | +Pass `licenseKey` and `telemetry` in your SuperDoc or SuperEditor config: |
| 45 | + |
| 46 | +<CodeGroup> |
| 47 | + |
| 48 | +```javascript SuperDoc |
| 49 | +import { SuperDoc } from 'superdoc'; |
| 50 | + |
| 51 | +const superdoc = new SuperDoc({ |
| 52 | + selector: '#editor', |
| 53 | + document: yourFile, |
| 54 | + licenseKey: 'your-license-key', |
| 55 | + telemetry: { |
| 56 | + enabled: true, |
| 57 | + }, |
| 58 | +}); |
| 59 | +``` |
| 60 | + |
| 61 | +```javascript SuperEditor |
| 62 | +import { Editor } from 'superdoc/super-editor'; |
| 63 | + |
| 64 | +const editor = await Editor.open(file, { |
| 65 | + element: document.querySelector('#editor'), |
| 66 | + licenseKey: 'your-license-key', |
| 67 | + telemetry: { |
| 68 | + enabled: true, |
| 69 | + }, |
| 70 | +}); |
| 71 | +``` |
| 72 | + |
| 73 | +</CodeGroup> |
| 74 | + |
| 75 | +### Options |
| 76 | + |
| 77 | +<ParamField path="licenseKey" type="string"> |
| 78 | + Your organization's license key. Links document opens to your account for billing. |
| 79 | + Defaults to `community-and-eval-agplv3` if not provided. |
| 80 | +</ParamField> |
| 81 | + |
| 82 | +<ParamField path="telemetry.enabled" type="boolean"> |
| 83 | + Enable or disable telemetry. Default: `true`. |
| 84 | +</ParamField> |
| 85 | + |
| 86 | +<ParamField path="telemetry.endpoint" type="string"> |
| 87 | + Override the telemetry endpoint. Default: `https://ingest.superdoc.dev/v1/collect`. Useful for proxying through your own infrastructure. |
| 88 | +</ParamField> |
| 89 | + |
| 90 | +<ParamField path="telemetry.metadata" type="Record<string, unknown>"> |
| 91 | + Custom key-value pairs included with every event. Use this to attach your own identifiers (customer ID, environment, etc.). |
| 92 | +</ParamField> |
| 93 | + |
| 94 | +### Disabling telemetry |
| 95 | + |
| 96 | +Set `enabled: false` to turn telemetry off entirely: |
| 97 | + |
| 98 | +```javascript |
| 99 | +const superdoc = new SuperDoc({ |
| 100 | + selector: '#editor', |
| 101 | + document: yourFile, |
| 102 | + telemetry: { |
| 103 | + enabled: false, |
| 104 | + }, |
| 105 | +}); |
| 106 | +``` |
| 107 | + |
| 108 | +No network requests will be made. Document metadata (GUID and timestamp) is still generated locally so files export correctly. |
| 109 | + |
| 110 | +## License key |
| 111 | + |
| 112 | +The license key identifies your organization. It's sent as an `X-License-Key` header with every telemetry request. |
| 113 | + |
| 114 | +| License type | Key | How to get it | |
| 115 | +|-------------|-----|---------------| |
| 116 | +| Community / evaluation | `community-and-eval-agplv3` (default) | No action needed — used automatically | |
| 117 | +| Commercial | Your organization key | Email [q@superdoc.dev](mailto:q@superdoc.dev) | |
| 118 | + |
| 119 | +If you're evaluating SuperDoc or using it under AGPLv3, you don't need to configure a license key. The community key is applied automatically. |
| 120 | + |
| 121 | +For a commercial license key, email [q@superdoc.dev](mailto:q@superdoc.dev). You'll receive a key tied to your organization that unlocks usage tracking for your account. |
| 122 | + |
| 123 | +## How document uniqueness works |
| 124 | + |
| 125 | +SuperDoc needs to identify each document uniquely so that opening the same file twice counts as one document, not two. This matters for accurate billing. |
| 126 | + |
| 127 | +### Identifier strategies |
| 128 | + |
| 129 | +SuperDoc uses two strategies depending on what metadata the file contains: |
| 130 | + |
| 131 | +**1. Metadata hash — file already has a GUID and timestamp** |
| 132 | + |
| 133 | +DOCX files created by Microsoft Word (and other tools) typically contain a unique GUID and a creation timestamp in their internal metadata (`docProps/` and `word/settings.xml`). When both are present, SuperDoc hashes them together using CRC32: |
| 134 | + |
| 135 | +``` |
| 136 | +documentId = CRC32(GUID | creationTimestamp) → "HASH-A1B2C3D4" |
| 137 | +``` |
| 138 | + |
| 139 | +This is the most stable strategy. The same file always produces the same identifier regardless of content edits, because the hash is derived from metadata, not content. |
| 140 | + |
| 141 | +**2. Generated identifier — file is missing metadata** |
| 142 | + |
| 143 | +Some tools produce DOCX files without a GUID or timestamp. When either is missing, SuperDoc does two things: |
| 144 | + |
| 145 | +1. **For the current open**: generates a content hash (CRC32 of the raw file bytes) so the same file still produces a consistent identifier |
| 146 | +2. **For future opens**: generates the missing GUID and/or timestamp and embeds them into the document's metadata |
| 147 | + |
| 148 | +The generated metadata is saved when you export. On the next import, the file now has both a GUID and timestamp, so SuperDoc switches to the stable metadata hash automatically. |
| 149 | + |
| 150 | +``` |
| 151 | +First open: no GUID in file → content hash used, GUID + timestamp generated |
| 152 | +Export: GUID + timestamp written into the file |
| 153 | +Next open: GUID + timestamp found → metadata hash (stable from now on) |
| 154 | +``` |
| 155 | + |
| 156 | +This self-healing behavior means document identification improves automatically as files pass through SuperDoc. After one export cycle, every document gets a permanent, edit-resistant identifier. |
| 157 | + |
| 158 | +## Payload example |
| 159 | + |
| 160 | +Here's what a telemetry request looks like on the wire: |
| 161 | + |
| 162 | +``` |
| 163 | +POST https://ingest.superdoc.dev/v1/collect |
| 164 | +Content-Type: application/json |
| 165 | +X-License-Key: your-license-key |
| 166 | +``` |
| 167 | + |
| 168 | +```json |
| 169 | +{ |
| 170 | + "superdocVersion": "1.15.0", |
| 171 | + "browserInfo": { |
| 172 | + "userAgent": "Mozilla/5.0...", |
| 173 | + "currentUrl": "https://app.example.com/doc/123", |
| 174 | + "hostname": "app.example.com", |
| 175 | + "screenSize": { "width": 1920, "height": 1080 } |
| 176 | + }, |
| 177 | + "metadata": { |
| 178 | + "customerId": "cust-456" |
| 179 | + }, |
| 180 | + "events": [ |
| 181 | + { |
| 182 | + "timestamp": "2026-02-12T14:30:00.000Z", |
| 183 | + "documentId": "a1b2c3d4e5f6...", |
| 184 | + "documentCreatedAt": "2024-01-15T10:30:00Z" |
| 185 | + } |
| 186 | + ] |
| 187 | +} |
| 188 | +``` |
| 189 | + |
| 190 | +## Try it: document counting demo |
| 191 | + |
| 192 | +See document uniqueness in action. Upload a DOCX file and watch the counter — then try the steps below. |
| 193 | + |
| 194 | +import { DocCounter } from '/snippets/components/doc-counter.jsx' |
| 195 | + |
| 196 | +<DocCounter height="300px" /> |
| 197 | + |
| 198 | +<Steps> |
| 199 | + <Step title="Upload a DOCX file"> |
| 200 | + Click **Upload DOCX** and pick any `.docx` file. The counter goes to **1**. SuperDoc reads the file's internal metadata and generates a document identifier. |
| 201 | + </Step> |
| 202 | + <Step title="Edit the document"> |
| 203 | + Make some changes in the editor — add text, delete a paragraph, change formatting. The identifier stays the same because it's based on metadata, not content. |
| 204 | + </Step> |
| 205 | + <Step title="Export and re-import"> |
| 206 | + Click **Export & re-import**. SuperDoc exports the document to DOCX and immediately re-imports it. The counter stays at **1** — same metadata, same identifier. |
| 207 | + </Step> |
| 208 | + <Step title="Upload a different file"> |
| 209 | + Upload a second DOCX file. The counter goes to **2**. Each file with distinct metadata gets its own identifier. |
| 210 | + </Step> |
| 211 | + <Step title="Re-upload the first file"> |
| 212 | + Upload the original file again. The counter stays at **2**. SuperDoc recognizes it as the same document. |
| 213 | + </Step> |
| 214 | +</Steps> |
| 215 | + |
| 216 | +<Info> |
| 217 | +The event log at the bottom shows exactly what SuperDoc sees: the identifier hash, whether a document is new or recognized, and how many times each has been opened. |
| 218 | +</Info> |
| 219 | + |
| 220 | +## FAQ |
| 221 | + |
| 222 | +<AccordionGroup> |
| 223 | + |
| 224 | +<Accordion title="Does telemetry affect performance?"> |
| 225 | +No. The request is non-blocking and fire-and-forget. Your editor loads and renders regardless of the telemetry outcome. |
| 226 | +</Accordion> |
| 227 | + |
| 228 | +<Accordion title="What happens if telemetry fails?"> |
| 229 | +Nothing. Errors are caught silently. No retries, no queuing, no user-visible errors. Your app continues to work normally. |
| 230 | +</Accordion> |
| 231 | + |
| 232 | +<Accordion title="Can I route telemetry through my own server?"> |
| 233 | +Yes. Set `telemetry.endpoint` to your proxy URL. The payload format stays the same. |
| 234 | +</Accordion> |
| 235 | + |
| 236 | +<Accordion title="Does the same document get counted twice?"> |
| 237 | +Not if it has metadata. SuperDoc hashes the document's GUID and creation timestamp, so the same file produces the same identifier every time. See [How document uniqueness works](#how-document-uniqueness-works) above. |
| 238 | +</Accordion> |
| 239 | + |
| 240 | +<Accordion title="Do I need a license key for open-source use?"> |
| 241 | +No. The community key (`community-and-eval-agplv3`) is applied automatically when you don't provide one. |
| 242 | +</Accordion> |
| 243 | + |
| 244 | +</AccordionGroup> |
0 commit comments