Skip to content

feat(onboarding): funnel analytics for the new flow#7960

Open
talissoncosta wants to merge 4 commits into
mainfrom
feat/onboarding-analytics-7738
Open

feat(onboarding): funnel analytics for the new flow#7960
talissoncosta wants to merge 4 commits into
mainfrom
feat/onboarding-analytics-7738

Conversation

@talissoncosta

@talissoncosta talissoncosta commented Jul 7, 2026

Copy link
Copy Markdown
Contributor
  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Contributes to #7738.

Funnel analytics for the new single-page onboarding flow. It now emits the same milestone events as the current flow, tags the variant it served, and adds new-flow-only diagnostics. Funnel analytics only. The multivariate flag and a true A/B split (tagging the control arm) are a follow-up.

  • onboarding_variant user property (control | single_page), set at the getting-started gate when a user reaches onboarding (not at identify), from the onboarding_quickstart_flow flag. Tags which flow the user saw, so onboarding events can be grouped by it.
  • Milestone events from the new flow. It auto-creates the project and flag via RTK, which emitted nothing, so the funnel had no project/feature step. It now fires First Project created / First Feature created on a real create (org already fired). Milestone events only, not the generic Project/Feature created actions, which stay reserved for resources a user makes by hand.
  • New-flow-only diagnostics for internal drop-off: Onboarding snippet copied (install / wire), Onboarding AI connect used, Onboarding flag toggled.

Follow-ups: multivariate flag plus control-arm tagging for a true A/B split; activation (first SDK evaluation, pending #7623); shared-analytics hardening (setOnce, trackEvent try/catch) in #8061.

How did you test this code?

Manually, with onboarding_quickstart_flow on and analytics logging enabled (or by spying on API.trackEvent / API.trackTraits in the console):

  1. Sign up and land on the flow; confirm onboarding_variant = single_page is set once at the gate.
  2. Confirm First Project created / First Feature created fire once on the auto-bootstrap, and not again on revisit.
  3. Copy a snippet, copy the AI prompt, toggle the flag; confirm the three diagnostics events (the toggle event only after it saves).

@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flagsmith-frontend-preview Ready Ready Preview, Comment Jul 22, 2026 6:37pm
flagsmith-frontend-staging Ready Ready Preview, Comment Jul 22, 2026 6:37pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview Jul 22, 2026 6:37pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds onboarding event definitions, feature-flag-based variant helpers, one-time variant trait tracking, and analytics for prompt copies, snippets, flag toggles, project creation, and first-feature creation. Connect-panel callbacks now propagate copy actions, while flag toggling reports success through a boolean promise. Event tracking also validates payloads and catches dispatch errors.

Estimated code review effort: 3 (Moderate) | ~25 minutes


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added feature New feature or request front-end Issue related to the React Front End Dashboard labels Jul 7, 2026
@talissoncosta
talissoncosta force-pushed the feat/onboarding-analytics-7738 branch from 97fe9e6 to 10fa440 Compare July 7, 2026 20:01
@github-actions github-actions Bot added feature New feature or request and removed feature New feature or request labels Jul 7, 2026
@talissoncosta
talissoncosta force-pushed the feat/onboarding-analytics-7738 branch 2 times, most recently from 3a4e76d to 0a430fe Compare July 7, 2026 20:08
@github-actions github-actions Bot added feature New feature or request and removed feature New feature or request labels Jul 7, 2026
@github-actions github-actions Bot added feature New feature or request and removed feature New feature or request labels Jul 7, 2026
@talissoncosta
talissoncosta force-pushed the feat/onboarding-analytics-7738 branch from 0a430fe to 5492b47 Compare July 7, 2026 20:19
@github-actions github-actions Bot added feature New feature or request and removed feature New feature or request labels Jul 7, 2026
@talissoncosta
talissoncosta marked this pull request as ready for review July 8, 2026 11:53
@talissoncosta
talissoncosta requested a review from a team as a code owner July 8, 2026 11:53
@talissoncosta
talissoncosta requested review from kyle-ssg and removed request for a team July 8, 2026 11:53
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Docker builds report

Image Build Status Security report
ghcr.io/flagsmith/flagsmith-api-test:pr-7960 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-e2e:pr-7960 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-api:pr-7960 Finished ✅ Results
ghcr.io/flagsmith/flagsmith:pr-7960 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-private-cloud:pr-7960 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-frontend:pr-7960 Finished ✅ Results

@Zaimwa9 Zaimwa9 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmh, sorry overall I feel that the whole flag/variant/tracking management is done at the wrong place and should be using a multivariate flag (if not an experimentation but that can be done later on).

I don't think the tracking should happen in identify:

  1. API.identify runs on every user model load and the variant could change over time
  2. The real tracking should happen when we consume the variant (GettingStartedGate.tsx seems like the right place)
  3. We would track it on 3 years old accounts for example and/or on users that never reach the onboarding, meaning we would corrupt the data

Let me know if i'm missing something

Comment on lines +5 to +6
// Which onboarding flow the user is in, from the onboarding_quickstart_flow
// flag the new flow is gated behind (#7738).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove this comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, removed in c67bc32

}),
)
.unwrap()
// Milestone, not action (see the project create above): First only.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same. Can you go over the comments and only leave the ones clearly stating what is happening?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done removed in 30ffd6c. Trimmed the narrative comments, left only the two flagging
non-obvious behaviour.

Comment on lines +7 to +10
export const getOnboardingVariant = (): OnboardingVariant =>
Utils.getFlagsmithHasFeature('onboarding_quickstart_flow')
? 'single_page'
: 'control'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we plan to release this one ? Should we directly have 2 variants in the feature and grab the variant name from the flag ?

@talissoncosta talissoncosta Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question @Zaimwa9. I think this concern will be addressed on next issue. I will keep it simple now, ff will be boolean for now until we decided the path forward.

Comment thread frontend/web/project/api.ts Outdated
// Pin the onboarding variant as a user property once the flag has
// resolved, so every event (incl. autocapture pageviews) is attributable
// to control vs single_page in one funnel (#7738).
API.flagsmithIdentify()?.then(() =>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could have it in a finally maybe to also grab the default value ?

This means we are setting it each time we identify a user ?

All users are getting an onboardingVariant trait while they haven't gone through the onboarding ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checked, we have this amplitude method to Identify.setOnce to avoid mutating it

@talissoncosta talissoncosta Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call @Zaimwa9. I will revert the changes on api.ts in order to keep this PR clean with the funnel analytics and will create follow up PR's to address your concerns.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it on a follow-up #8061, to keep this PR onboarding-only.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f40ac417-b58c-44c5-bc90-9f9d8ece7b77

📥 Commits

Reviewing files that changed from the base of the PR and between 5291318 and af03032.

📒 Files selected for processing (9)
  • frontend/common/utils/getOnboardingVariant.ts
  • frontend/e2e/tests/initialise-tests.pw.ts
  • frontend/e2e/tests/onboarding-tests.pw.ts
  • frontend/web/components/App.js
  • frontend/web/components/pages/onboarding/GettingStartedGate.tsx
  • frontend/web/components/pages/onboarding/OnboardingFlow/OnboardingFlow.tsx
  • frontend/web/components/pages/onboarding/hooks/bootstrapOnboarding.ts
  • frontend/web/components/pages/onboarding/hooks/useOnboardingFlag.ts
  • frontend/web/project/api.ts

Comment thread frontend/web/project/api.ts Outdated
Comment thread frontend/web/project/api.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
frontend/web/project/api.ts (1)

313-323: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Move validation outside the Google Analytics check and handle promise rejection.

The event validation and debug logging are nested inside if (Project.ga), meaning they won't run for Amplitude-only setups. Furthermore, API.postEvent returns a promise that could reject, but the synchronous try/catch won't catch it, leading to an unhandled promise rejection.

♻️ Proposed fix
-      if (Project.ga) {
-        if (Project.logAnalytics) console.log('ANALYTICS EVENT', data)
-        if (!data || !data.category || !data.event)
-          return console.error('Invalid event provided', data)
-        if (data.category === 'First')
-          API.postEvent(
-            `${data.event}${
-              data.extra ? ` ${JSON.stringify(data.extra)}` : ''
-            }`,
-            'first_events',
-          )
+      if (Project.logAnalytics) console.log('ANALYTICS EVENT', data)
+      if (!data || !data.category || !data.event)
+        return console.error('Invalid event provided', data)
+
+      if (data.category === 'First') {
+        API.postEvent(
+          `${data.event}${data.extra ? ` ${JSON.stringify(data.extra)}` : ''}`,
+          'first_events',
+        )?.catch((err) => console.error('Error posting first event', err))
+      }
+
+      if (Project.ga) {
         ga('send', {

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2035470c-64b7-49b0-8914-284551309112

📥 Commits

Reviewing files that changed from the base of the PR and between af03032 and 71aecb7.

📒 Files selected for processing (9)
  • frontend/common/constants.ts
  • frontend/common/utils/getOnboardingVariant.ts
  • frontend/web/components/pages/onboarding/GettingStartedGate.tsx
  • frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectWithAiPanel.tsx
  • frontend/web/components/pages/onboarding/OnboardingConnectPanel/OnboardingConnectPanel.tsx
  • frontend/web/components/pages/onboarding/OnboardingFlow/OnboardingFlow.tsx
  • frontend/web/components/pages/onboarding/hooks/bootstrapOnboarding.ts
  • frontend/web/components/pages/onboarding/hooks/useOnboardingFlag.ts
  • frontend/web/project/api.ts

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor
✅ private-cloud · depot-ubuntu-latest-16 — run #18636 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  5 passed

Details

stats  5 tests across 5 suites
duration  1 minute, 1 second
commit  df6090f
info  🔄 Run: #18636 (attempt 1)

🗂️ Previous results
✅ private-cloud · depot-ubuntu-latest-arm-16 — run #18636 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  36.7 seconds
commit  df6090f
info  🔄 Run: #18636 (attempt 1)

✅ oss · depot-ubuntu-latest-16 — run #18636 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  42.8 seconds
commit  df6090f
info  🔄 Run: #18636 (attempt 1)

✅ oss · depot-ubuntu-latest-arm-16 — run #18636 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  45.6 seconds
commit  df6090f
info  🔄 Run: #18636 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-16 — run #18634 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  1 minute, 4 seconds
commit  204912f
info  🔄 Run: #18634 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-arm-16 — run #18634 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  4 passed

Details

stats  4 tests across 3 suites
duration  1 minute, 3 seconds
commit  204912f
info  🔄 Run: #18634 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-16 — run #18633 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  34.6 seconds
commit  45ab19a
info  🔄 Run: #18633 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-arm-16 — run #18633 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  3 passed

Details

stats  3 tests across 3 suites
duration  35.4 seconds
commit  45ab19a
info  🔄 Run: #18633 (attempt 1)

✅ oss · depot-ubuntu-latest-16 — run #18634 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  42.9 seconds
commit  204912f
info  🔄 Run: #18634 (attempt 1)

✅ oss · depot-ubuntu-latest-arm-16 — run #18634 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  41.9 seconds
commit  204912f
info  🔄 Run: #18634 (attempt 1)

✅ oss · depot-ubuntu-latest-arm-16 — run #18633 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  41.2 seconds
commit  45ab19a
info  🔄 Run: #18633 (attempt 1)

✅ oss · depot-ubuntu-latest-16 — run #18633 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  41.1 seconds
commit  45ab19a
info  🔄 Run: #18633 (attempt 1)

@github-actions

Copy link
Copy Markdown
Contributor
✅ oss · depot-ubuntu-latest-arm-16 — run #18572 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  45.1 seconds
commit  71aecb7
info  🔄 Run: #18572 (attempt 1)

talissoncosta and others added 3 commits July 21, 2026 15:16
…otstrap

The single-page flow auto-creates the project and flag, which emitted
nothing, so the funnel had no project/feature step. Fire First Project
created / First Feature created on a real create.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Onboarding snippet copied (install/wire), Onboarding AI connect used, and
Onboarding flag toggled (fired only after the toggle saves; toggle now
returns success). For measuring internal drop-off in the new flow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Set the onboarding_variant user property (control | single_page) when the
user reaches the gate, derived from the onboarding_quickstart_flow flag.
Tagged at the point of consumption, not in identify, so only users who
reach onboarding get it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@talissoncosta
talissoncosta force-pushed the feat/onboarding-analytics-7738 branch from da1ace9 to c67bc32 Compare July 21, 2026 18:17
talissoncosta added a commit that referenced this pull request Jul 21, 2026
Use amplitude setOnce for onboarding_variant so it's pinned to the user's
first exposure and doesn't get overwritten on later loads. Adds
API.trackTraitsOnce; the getting-started gate uses it. Addresses Wadii's
review note on #7960.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added feature New feature or request and removed feature New feature or request labels Jul 21, 2026
talissoncosta added a commit that referenced this pull request Jul 21, 2026
A failing tracker (GA/amplitude) can't break the caller, e.g. the
onboarding bootstrap firing milestone events. Addresses kyle's note on
#7960.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
const variant = getOnboardingVariant()

useEffect(() => {
API.trackTraits({ onboarding_variant: variant })

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tagged at the gate (only users who reach onboarding). set for now; immutable setOnce in #8061.

@Zaimwa9 Zaimwa9 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One change to use the right property

Comment on lines +10 to +16
export const getOnboardingVariant = (): OnboardingVariant => {
if (!Utils.getFlagsmithHasFeature('onboarding_quickstart_flow')) {
return 'control'
}
const value = Utils.getFlagsmithValue('onboarding_quickstart_flow')
return isOnboardingVariant(value) ? value : 'single_page'
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, see here https://github.com/Flagsmith/flagsmith/pull/7979/changes#diff-da830800eab2c18085ef679517e14d18836f9d0db7940a925117f4bd8c5c565bR27-R28

We should have access to the variant NAME directly, so no need to use the value at all normally

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed df6090f, reading the arm from flag.variant. Is that what you meant? Left getExperimentFlag for the experimentation follow-up, glad to hear your thoughts.

Review feedback: the identity flags response names the served variant
(the MV option key, or the reserved 'control' for the default arm), so
the arm comes from flag.variant and the flag's value stays free. An
enabled flag with no variant is the pre-conversion boolean, meaning
the new flow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request front-end Issue related to the React Front End Dashboard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Onboarding: funnel analytics + variant tagging for the new flow

3 participants