Skip to content

Commit

Permalink
fix: improve survey bundle size
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasheriques committed Feb 22, 2025
1 parent 9b9c658 commit 9d1bfd9
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 135 deletions.
3 changes: 1 addition & 2 deletions src/entrypoints/surveys-preview.es.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export { renderFeedbackWidgetPreview, renderSurveysPreview } from '../extensions/surveys'
export { getNextSurveyStep } from '../posthog-surveys'
export { getNextSurveyStep, renderFeedbackWidgetPreview, renderSurveysPreview } from '../extensions/surveys'
116 changes: 104 additions & 12 deletions src/extensions/surveys.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,109 @@ const logger = createLogger('[Surveys]')
const window = _window as Window & typeof globalThis
const document = _document as Document

function getRatingBucketForResponseValue(responseValue: number, scale: number) {
if (scale === 3) {
if (responseValue < 1 || responseValue > 3) {
throw new Error('The response must be in range 1-3')
}

return responseValue === 1 ? 'negative' : responseValue === 2 ? 'neutral' : 'positive'
} else if (scale === 5) {
if (responseValue < 1 || responseValue > 5) {
throw new Error('The response must be in range 1-5')
}

return responseValue <= 2 ? 'negative' : responseValue === 3 ? 'neutral' : 'positive'
} else if (scale === 7) {
if (responseValue < 1 || responseValue > 7) {
throw new Error('The response must be in range 1-7')
}

return responseValue <= 3 ? 'negative' : responseValue === 4 ? 'neutral' : 'positive'
} else if (scale === 10) {
if (responseValue < 0 || responseValue > 10) {
throw new Error('The response must be in range 0-10')
}

return responseValue <= 6 ? 'detractors' : responseValue <= 8 ? 'passives' : 'promoters'
}

throw new Error('The scale must be one of: 3, 5, 7, 10')
}

export function getNextSurveyStep(
survey: Survey,
currentQuestionIndex: number,
response: string | string[] | number | null
) {
const question = survey.questions[currentQuestionIndex]
const nextQuestionIndex = currentQuestionIndex + 1

if (!question.branching?.type) {
if (currentQuestionIndex === survey.questions.length - 1) {
return SurveyQuestionBranchingType.End
}

return nextQuestionIndex
}

if (question.branching.type === SurveyQuestionBranchingType.End) {
return SurveyQuestionBranchingType.End
} else if (question.branching.type === SurveyQuestionBranchingType.SpecificQuestion) {
if (Number.isInteger(question.branching.index)) {
return question.branching.index
}
} else if (question.branching.type === SurveyQuestionBranchingType.ResponseBased) {
// Single choice
if (question.type === SurveyQuestionType.SingleChoice) {
// :KLUDGE: for now, look up the choiceIndex based on the response
// TODO: once QuestionTypes.MultipleChoiceQuestion is refactored, pass the selected choiceIndex into this method
const selectedChoiceIndex = question.choices.indexOf(`${response}`)

if (question.branching?.responseValues?.hasOwnProperty(selectedChoiceIndex)) {
const nextStep = question.branching.responseValues[selectedChoiceIndex]

// Specific question
if (Number.isInteger(nextStep)) {
return nextStep
}

if (nextStep === SurveyQuestionBranchingType.End) {
return SurveyQuestionBranchingType.End
}

return nextQuestionIndex
}
} else if (question.type === SurveyQuestionType.Rating) {
if (typeof response !== 'number' || !Number.isInteger(response)) {
throw new Error('The response type must be an integer')
}

const ratingBucket = getRatingBucketForResponseValue(response, question.scale)

if (question.branching?.responseValues?.hasOwnProperty(ratingBucket)) {
const nextStep = question.branching.responseValues[ratingBucket]

// Specific question
if (Number.isInteger(nextStep)) {
return nextStep
}

if (nextStep === SurveyQuestionBranchingType.End) {
return SurveyQuestionBranchingType.End
}

return nextQuestionIndex
}
}

return nextQuestionIndex
}

logger.warn('Falling back to next question index due to unexpected branching type')
return nextQuestionIndex
}

export class SurveyManager {
private posthog: PostHog
private surveyInFocus: string | null
Expand Down Expand Up @@ -663,18 +766,7 @@ export function Questions({

setQuestionsResponses({ ...questionsResponses, [responseKey]: res })

// Old SDK, no branching
if (!posthog.getNextSurveyStep) {
const isLastDisplayedQuestion = displayQuestionIndex === survey.questions.length - 1
if (isLastDisplayedQuestion) {
sendSurveyEvent({ ...questionsResponses, [responseKey]: res }, survey, posthog)
} else {
setCurrentQuestionIndex(displayQuestionIndex + 1)
}
return
}

const nextStep = posthog.getNextSurveyStep(survey, displayQuestionIndex, res)
const nextStep = getNextSurveyStep(survey, displayQuestionIndex, res)
if (nextStep === SurveyQuestionBranchingType.End) {
sendSurveyEvent({ ...questionsResponses, [responseKey]: res }, survey, posthog)
} else {
Expand Down
11 changes: 1 addition & 10 deletions src/posthog-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import { PageViewManager } from './page-view'
import { PostHogSurveys } from './posthog-surveys'
import { RateLimiter } from './rate-limiter'
import { uuidv7 } from './uuidv7'
import { Survey, SurveyCallback, SurveyQuestionBranchingType } from './posthog-surveys-types'
import { SurveyCallback } from './posthog-surveys-types'
import {
isArray,
isEmptyObject,
Expand Down Expand Up @@ -1341,15 +1341,6 @@ export class PostHog {
this.surveys.canRenderSurvey(surveyId)
}

/** Get the next step of the survey: a question index or `end` */
getNextSurveyStep(
survey: Survey,
currentQuestionIndex: number,
response: string | string[] | number | null
): number | SurveyQuestionBranchingType.End {
return this.surveys.getNextSurveyStep(survey, currentQuestionIndex, response)
}

/**
* Identify a user with a unique ID instead of a PostHog
* randomly generated distinct_id. If the method is never called,
Expand Down
112 changes: 1 addition & 111 deletions src/posthog-surveys.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { SURVEYS } from './constants'
import { getSurveySeenStorageKeys } from './extensions/surveys/surveys-utils'
import { PostHog } from './posthog-core'
import {
Survey,
SurveyCallback,
SurveyMatchType,
SurveyQuestionBranchingType,
SurveyQuestionType,
} from './posthog-surveys-types'
import { Survey, SurveyCallback, SurveyMatchType } from './posthog-surveys-types'
import { RemoteConfig } from './types'
import { Info } from './utils/event-utils'
import { assignableWindow, document, userAgent, window } from './utils/globals'
Expand All @@ -32,109 +26,6 @@ export const surveyValidationMap: Record<SurveyMatchType, (targets: string[], va
is_not: (targets, value) => targets.every((target) => value !== target),
}

function getRatingBucketForResponseValue(responseValue: number, scale: number) {
if (scale === 3) {
if (responseValue < 1 || responseValue > 3) {
throw new Error('The response must be in range 1-3')
}

return responseValue === 1 ? 'negative' : responseValue === 2 ? 'neutral' : 'positive'
} else if (scale === 5) {
if (responseValue < 1 || responseValue > 5) {
throw new Error('The response must be in range 1-5')
}

return responseValue <= 2 ? 'negative' : responseValue === 3 ? 'neutral' : 'positive'
} else if (scale === 7) {
if (responseValue < 1 || responseValue > 7) {
throw new Error('The response must be in range 1-7')
}

return responseValue <= 3 ? 'negative' : responseValue === 4 ? 'neutral' : 'positive'
} else if (scale === 10) {
if (responseValue < 0 || responseValue > 10) {
throw new Error('The response must be in range 0-10')
}

return responseValue <= 6 ? 'detractors' : responseValue <= 8 ? 'passives' : 'promoters'
}

throw new Error('The scale must be one of: 3, 5, 7, 10')
}

export function getNextSurveyStep(
survey: Survey,
currentQuestionIndex: number,
response: string | string[] | number | null
) {
const question = survey.questions[currentQuestionIndex]
const nextQuestionIndex = currentQuestionIndex + 1

if (!question.branching?.type) {
if (currentQuestionIndex === survey.questions.length - 1) {
return SurveyQuestionBranchingType.End
}

return nextQuestionIndex
}

if (question.branching.type === SurveyQuestionBranchingType.End) {
return SurveyQuestionBranchingType.End
} else if (question.branching.type === SurveyQuestionBranchingType.SpecificQuestion) {
if (Number.isInteger(question.branching.index)) {
return question.branching.index
}
} else if (question.branching.type === SurveyQuestionBranchingType.ResponseBased) {
// Single choice
if (question.type === SurveyQuestionType.SingleChoice) {
// :KLUDGE: for now, look up the choiceIndex based on the response
// TODO: once QuestionTypes.MultipleChoiceQuestion is refactored, pass the selected choiceIndex into this method
const selectedChoiceIndex = question.choices.indexOf(`${response}`)

if (question.branching?.responseValues?.hasOwnProperty(selectedChoiceIndex)) {
const nextStep = question.branching.responseValues[selectedChoiceIndex]

// Specific question
if (Number.isInteger(nextStep)) {
return nextStep
}

if (nextStep === SurveyQuestionBranchingType.End) {
return SurveyQuestionBranchingType.End
}

return nextQuestionIndex
}
} else if (question.type === SurveyQuestionType.Rating) {
if (typeof response !== 'number' || !Number.isInteger(response)) {
throw new Error('The response type must be an integer')
}

const ratingBucket = getRatingBucketForResponseValue(response, question.scale)

if (question.branching?.responseValues?.hasOwnProperty(ratingBucket)) {
const nextStep = question.branching.responseValues[ratingBucket]

// Specific question
if (Number.isInteger(nextStep)) {
return nextStep
}

if (nextStep === SurveyQuestionBranchingType.End) {
return SurveyQuestionBranchingType.End
}

return nextQuestionIndex
}
}

return nextQuestionIndex
}

logger.warn('Falling back to next question index due to unexpected branching type')
return nextQuestionIndex
}

function defaultMatchType(matchType?: SurveyMatchType): SurveyMatchType {
return matchType ?? 'icontains'
}
Expand Down Expand Up @@ -375,7 +266,6 @@ export class PostHogSurveys {
return this.instance.featureFlags.isFeatureEnabled(value)
})
}
getNextSurveyStep = getNextSurveyStep

// this method is lazily loaded onto the window to avoid loading preact and other dependencies if surveys is not enabled
private _canActivateRepeatedly(survey: Survey) {
Expand Down

0 comments on commit 9d1bfd9

Please sign in to comment.