mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat(feedback): gate onboarding survey on first processing, add prompt lifecycle events (#615)
Defers the onboarding usage survey to the instance's first successful processing (the worker writes a one-time onboarding.firstProcessedAt marker and the overlay gates on it), so it reaches engaged users instead of first-landing visitors. Replaces the two questions telemetry already answers (modality preference from tool_used, install method from instance_started) with what it can't infer: prior tool, self-host motivation, and discovery source. Adds feedback_prompt_shown and feedback_prompt_dismissed on all five feedback surfaces (usage survey, per-job prompt, admin install card, global nav dialog, search-miss) so skip and completion rates are measurable, not just submissions. New survey strings translated into all 20 non-English locales.
This commit is contained in:
@@ -97,10 +97,14 @@ describe("shouldShowInstallFeedbackCard", () => {
|
||||
});
|
||||
|
||||
describe("shouldShowUsageSurvey", () => {
|
||||
it("shows only for admins after analytics config is loaded and enabled", () => {
|
||||
// The survey now waits for the instance's first successful processing so we
|
||||
// ask engaged users, not someone staring at an empty app on first landing.
|
||||
const PROCESSED = { "onboarding.firstProcessedAt": "2026-01-14T00:00:00Z" };
|
||||
|
||||
it("shows only for admins after analytics is loaded and enabled, once a processing has completed", () => {
|
||||
expect(
|
||||
shouldShowUsageSurvey({
|
||||
settings: {},
|
||||
settings: PROCESSED,
|
||||
role: "admin",
|
||||
analyticsConfigLoaded: true,
|
||||
analyticsEnabled: true,
|
||||
@@ -109,7 +113,7 @@ describe("shouldShowUsageSurvey", () => {
|
||||
|
||||
expect(
|
||||
shouldShowUsageSurvey({
|
||||
settings: {},
|
||||
settings: PROCESSED,
|
||||
role: "user",
|
||||
analyticsConfigLoaded: true,
|
||||
analyticsEnabled: true,
|
||||
@@ -118,7 +122,7 @@ describe("shouldShowUsageSurvey", () => {
|
||||
|
||||
expect(
|
||||
shouldShowUsageSurvey({
|
||||
settings: {},
|
||||
settings: PROCESSED,
|
||||
role: "admin",
|
||||
analyticsConfigLoaded: false,
|
||||
analyticsEnabled: true,
|
||||
@@ -127,7 +131,7 @@ describe("shouldShowUsageSurvey", () => {
|
||||
|
||||
expect(
|
||||
shouldShowUsageSurvey({
|
||||
settings: {},
|
||||
settings: PROCESSED,
|
||||
role: "admin",
|
||||
analyticsConfigLoaded: true,
|
||||
analyticsEnabled: false,
|
||||
@@ -135,10 +139,21 @@ describe("shouldShowUsageSurvey", () => {
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("stays hidden after answering or permanently dismissing", () => {
|
||||
it("stays hidden until the instance's first successful processing", () => {
|
||||
expect(
|
||||
shouldShowUsageSurvey({
|
||||
settings: { "onboarding.usageSurvey.answeredAt": "2026-01-14T00:00:00Z" },
|
||||
settings: {},
|
||||
role: "admin",
|
||||
analyticsConfigLoaded: true,
|
||||
analyticsEnabled: true,
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("stays hidden after answering or permanently dismissing, even once processing has happened", () => {
|
||||
expect(
|
||||
shouldShowUsageSurvey({
|
||||
settings: { ...PROCESSED, "onboarding.usageSurvey.answeredAt": "2026-01-14T00:00:00Z" },
|
||||
role: "admin",
|
||||
analyticsConfigLoaded: true,
|
||||
analyticsEnabled: true,
|
||||
@@ -147,7 +162,7 @@ describe("shouldShowUsageSurvey", () => {
|
||||
|
||||
expect(
|
||||
shouldShowUsageSurvey({
|
||||
settings: { "onboarding.usageSurvey.dismissedAt": "2026-01-14T00:00:00Z" },
|
||||
settings: { ...PROCESSED, "onboarding.usageSurvey.dismissedAt": "2026-01-14T00:00:00Z" },
|
||||
role: "admin",
|
||||
analyticsConfigLoaded: true,
|
||||
analyticsEnabled: true,
|
||||
|
||||
Reference in New Issue
Block a user