Skip to content

Commit 085601d

Browse files
feat: add telemetry documentation and implement document counting feature
- Introduced a new telemetry resource documentation in `resources/telemetry.mdx` detailing the telemetry data collection process and configuration options. - Updated `docs.json` to include the new telemetry documentation in the resources section. - Added a `DocCounter` component in `doc-counter.jsx` to track and display unique document counts during usage. - Enhanced the `SuperConverter` class to utilize SHA-256 for generating document identifiers, improving hash stability and security.
1 parent 5e52d7f commit 085601d

5 files changed

Lines changed: 549 additions & 21 deletions

File tree

apps/docs/docs.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,12 @@
221221
},
222222
{
223223
"group": "Resources",
224-
"pages": ["guides/general/accessibility", "guides/general/security", "resources/license"]
224+
"pages": [
225+
"guides/general/accessibility",
226+
"resources/telemetry",
227+
"guides/general/security",
228+
"resources/license"
229+
]
225230
}
226231
]
227232
},

apps/docs/resources/telemetry.mdx

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
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

Comments
 (0)