chore(launch): reconcile README/store live-status + add demo-funnel analytics (#111)

Two scoped changes for the no-spend growth launch (Growth Launch Kit,
Notion page 3a1ac25eb49f81099cc9f3a4286c8ec4):

1. README.md and distribution/play-listing.md said Google Play was
   "coming soon" / internal-testing-only, while distribution/retention-analysis.md
   and the live play.google.com listing show it's actually public with 1K+
   installs. Fixed the contradiction, added Google Play as a third install
   channel, and added an accurate mention of the new offline demo mode
   ("Try a Demo" — reasoning, grep, diff, permission prompt, ~30s, no server)
   matching what app/demo.tsx + src/lib/demo-script.ts actually render.
   play-listing.md's stale pre-launch checklists are marked historical
   instead of rewritten, so #83's ASO copy/keyword work is untouched.

2. Added the demo funnel's key metric (demo-completion, per the launch
   kit) as four consent-gated PostHog events: demo_started,
   demo_step_advanced, demo_completed, demo_exited_to_connect. Pure
   property-derivation logic lives in src/lib/demo-analytics.ts (no
   RN/PostHog imports, unit-tested with node --test, same pattern as
   analytics-classify.ts) and is wired into app/demo.tsx's lifecycle.
   Updated docs/analytics.md's event table and the privacy policy's event
   list (distribution/privacy-policy.md + its two HTML mirrors) per the
   repo's "new event requires a policy update" convention.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Den
2026-07-17 19:49:47 -07:00
committed by GitHub
parent c9ec92d8b7
commit 1ea84f8236
10 changed files with 220 additions and 37 deletions

View File

@@ -26,7 +26,7 @@ and reach first value (message sent → response received)?** Nothing else is tr
| Destination | PostHog **EU region** — `https://eu.i.posthog.com` (override: `EXPO_PUBLIC_POSTHOG_HOST`) |
| API key | `EXPO_PUBLIC_POSTHOG_KEY` (CI secret; unset ⇒ analytics is a strict no-op) |
| Identity | PostHog's random app-generated anonymous ID only; no `identify()` calls, no user IDs |
| Code | `src/lib/analytics.ts` (wrapper), `src/lib/analytics-classify.ts` (error bucketing), `src/lib/telemetry.ts` (consent gate) |
| Code | `src/lib/analytics.ts` (wrapper), `src/lib/analytics-classify.ts` (error bucketing), `src/lib/demo-analytics.ts` (demo-funnel property derivation), `src/lib/telemetry.ts` (consent gate) |
## Event schema
@@ -42,6 +42,10 @@ section 3a of `distribution/privacy-policy.md`.
| `connection_failed` | Health check fails | `source`, `error_class` | `src/stores/connections.ts` |
| `message_sent` | User sends a prompt to an agent session (excludes slash commands) | — | `src/stores/sessions.ts` |
| `response_received` | Agent response finishes streaming (busy → idle), excluding user-aborted runs | — | `src/stores/events.ts` |
| `demo_started` | The offline `/demo` screen mounts (no server, no network) | — | `app/demo.tsx` |
| `demo_step_advanced` | User advances a step in the scripted demo (currently: replies to the demo's permission prompt) | `step_index`, `step_name`, `reply` (`"once"` \| `"always"` \| `"reject"`) | `app/demo.tsx`, `src/lib/demo-analytics.ts` |
| `demo_completed` | The scripted demo reaches its end (completion or denial message shown) — the key demo activation metric | `outcome` (`"completed"` \| `"denied"`) | `app/demo.tsx`, `src/lib/demo-analytics.ts` |
| `demo_exited_to_connect` | User taps "Connect your own server" on the demo's CTA card | `reached_completion` (boolean) | `app/demo.tsx` |
`error_class` is one of a fixed enum — `malformed-url`, `no-internet`, `server-unreachable`,
`unauthorized`, `tls-error`, `timeout`, `unknown` (`src/lib/analytics-classify.ts`). The raw

View File

@@ -95,7 +95,7 @@
<header>
<h1>OpenCode Mobile — Privacy Policy</h1>
<p class="meta">
Effective date: 2026-05-24 &nbsp;|&nbsp;
Effective date: 2026-07-18 &nbsp;|&nbsp;
Operator: VIBE TECHNOLOGIES, LLC &nbsp;|&nbsp;
App: OpenCode Mobile (<code>cc.agentlabs.opencode</code>)
</p>
@@ -239,6 +239,27 @@
<td>An agent response finishes</td>
<td>—</td>
</tr>
<tr>
<td><code>demo_started</code></td>
<td>You open the offline "Try a Demo" screen (no server, no network)</td>
<td>—</td>
</tr>
<tr>
<td><code>demo_step_advanced</code></td>
<td>You reply to the demo's scripted permission prompt</td>
<td><code>step_index</code>, <code>step_name</code>, <code>reply</code> ("once", "always", or
"reject")</td>
</tr>
<tr>
<td><code>demo_completed</code></td>
<td>The scripted demo reaches its end</td>
<td><code>outcome</code> ("completed" or "denied")</td>
</tr>
<tr>
<td><code>demo_exited_to_connect</code></td>
<td>You tap "Connect your own server" on the demo's CTA</td>
<td><code>reached_completion</code> (true/false)</td>
</tr>
</tbody>
</table>
@@ -246,7 +267,8 @@
What analytics events <strong>never</strong> contain: your server URL, hostname, IP address,
or port; prompts, messages, or AI responses; code or file contents; tokens or credentials;
raw error messages. Connection failures are reduced to a fixed list of coarse categories
before being sent.
before being sent. The demo screen is fully offline and hardcoded — these events describe
interaction with the scripted walkthrough, never real session content.
</p>
<p>
Analytics data is sent to PostHog's <strong>EU region</strong> (<code>eu.i.posthog.com</code>)
@@ -469,7 +491,7 @@
<footer>
&copy; 2026 VIBE TECHNOLOGIES, LLC. OpenCode Mobile is MIT-licensed open-source software.
Privacy policy effective 2026-05-24.<br>
Privacy policy effective 2026-07-18.<br>
<a href="https://dzianisv.github.io/opencode-mobile/">Home</a> &middot;
<a href="https://dzianisv.github.io/opencode-mobile/guide/">Setup guide</a> &middot;
<a href="https://github.com/dzianisv/opencode-mobile">GitHub</a>