You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/product-analytics.md
+30-11Lines changed: 30 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,8 +1,9 @@
1
1
# Product usage analytics
2
2
3
-
Posecode keeps Vercel pageviews and product-usage events separate. Pageviews
4
-
answer “which routes were visited?”; the events below answer “did someone use
5
-
the product?”
3
+
Posecode keeps Vercel pageviews and product-usage events separate. One initial
4
+
pageview per loaded HTML entry point answers “which route was visited?”; the
5
+
deduplicated events below answer whether someone completed a meaningful product
6
+
step.
6
7
7
8
## Provider and production configuration
8
9
@@ -12,6 +13,13 @@ types, failure isolation, and session deduplication live in
12
13
`playground/src/vercel-analytics.ts`.
13
14
14
15
Vercel Web Analytics pageviews remain enabled without extra configuration.
16
+
The adapter disables soft-navigation tracking because the playground uses
17
+
`history.replaceState()` while editing; those source-address updates are not
18
+
new visits. Its `beforeSend` hook strips query strings and hashes, collapses
19
+
`/play/:movement` to `/play/[movement]`, and normalizes `.html` aliases before
20
+
the event leaves the browser. This prevents encoded movement source in a share
21
+
hash from becoming analytics URL data.
22
+
15
23
Vercel's current plan table says custom events are **not available on Hobby**;
16
24
they are available on Pro and Enterprise. Pro allows at most two properties per
17
25
custom event. The schema below deliberately stays within that limit.
@@ -40,7 +48,9 @@ Sources:
40
48
|`preset_opened`| A bundled movement is actually opened at initial load or selected in the library. |`source`: `library`, `direct_url`, `shared_link`, or `landing_cta`; `preset_id`: bundled stable ID |
41
49
|`editor_changed`| The first real CodeMirror user edit in the page session. Programmatic preset loads do not count. |`document_kind`: `preset`, `shared`, or `custom`|
42
50
|`render_succeeded`|`viewer.load()` successfully accepts a new meaningful document revision. Lazy boot and repeated recompiles of the same revision are deduplicated. The animation frame loop never emits this event. |`trigger`: `initial`, `preset_open`, `shared_link`, or `editor_change`; `document_kind`|
43
-
|`share_created`| The generated preset/encoded URL has successfully been written to the clipboard. |`share_kind`: `preset` or `encoded`|
51
+
|`prompt_copied`| The authoring guide is successfully copied on the landing page or playground. Repeated copies in one page session are deduplicated. |`location`: `landing` or `playground`|
52
+
|`movement_attempted`| The first user-initiated editor revision in the page session parses without errors, loads in the viewer, and does not exactly equal a bundled preset. Initial preset/shared loads and invalid edits do not count. | none |
53
+
|`share_created`| The generated preset/encoded URL has successfully been written to the clipboard. Repeated successful copies in one page session are deduplicated. |`share_kind`: `preset` or `encoded`|
44
54
|`embed_docs_clicked`| The embed documentation CTA on `/for-products` is clicked. |`location`: `for_products`|
45
55
|`install_command_copied`| An npm/npx command on `/for-products` is successfully written to the clipboard. |`command`: `embed`, `packages`, or `mcp`; `location`: `for_products`|
46
56
@@ -51,20 +61,29 @@ Useful readings include:
51
61
52
62
-`preset_opened` grouped by `source` separates library discovery from direct,
53
63
shared, and landing-page entry.
54
-
- Compare `editor_changed` and `render_succeeded` counts to see whether editing
55
-
reaches a valid renderer update. They are intentionally not a strict funnel:
56
-
initial and preset renders also count.
57
-
-`share_created` is a confirmed clipboard outcome, not a button-click count.
64
+
- Compare route visitors with `prompt_copied`, `movement_attempted`, and
65
+
`share_created` for the focused authoring funnel. These are aggregate counts,
66
+
not joined user records.
67
+
-`movement_attempted` excludes invalid edits and unchanged presets.
68
+
-`prompt_copied` and `share_created` are confirmed clipboard outcomes, not
69
+
button-click counts.
58
70
- Group `install_command_copied` by `command` to compare integration intent.
59
71
60
72
Vercel reports aggregate events rather than a user-level funnel. Do not attempt
61
73
to join individual visitors or reconstruct sessions from these payloads.
62
74
63
75
## Privacy and resilience
64
76
65
-
Events never contain Posecode source text, authoring prompts, personal data,
66
-
full share tokens, query strings, referrers, or sensitive URLs. `preset_id` is a
67
-
bounded public catalogue identifier; all other values are closed enums.
77
+
Custom event properties never contain Posecode source text, authoring prompts,
78
+
personal data, full share tokens, query strings, referrers, or sensitive URLs.
79
+
`preset_id` is a bounded public catalogue identifier; all other values are
80
+
closed enums.
81
+
82
+
Funnel deduplication is deliberately page-session-only and uses in-memory sets,
83
+
not cookies, local storage, user IDs, or source hashes. Reloading the page starts
84
+
a new page session. Vercel pageviews can still include Vercel's standard
85
+
anonymous dimensions and an incoming referrer under its Web Analytics privacy
86
+
model; the application does not add identifying fields.
68
87
69
88
Every analytics call is best-effort and catches provider failures. Ad blockers,
70
89
network failures, a missing provider configuration, or plan limitations do not
0 commit comments