Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add ios session replay onboarding #23190

Merged
merged 1 commit into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions frontend/src/scenes/onboarding/Onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { OnboardingReverseProxy } from './OnboardingReverseProxy'
import { FeatureFlagsSDKInstructions } from './sdks/feature-flags/FeatureFlagsSDKInstructions'
import { ProductAnalyticsSDKInstructions } from './sdks/product-analytics/ProductAnalyticsSDKInstructions'
import { SDKs } from './sdks/SDKs'
import { iOSInstructions } from './sdks/session-replay/ios'
import { SessionReplaySDKInstructions } from './sdks/session-replay/SessionReplaySDKInstructions'
import { SurveysSDKInstructions } from './sdks/surveys/SurveysSDKInstructions'

Expand Down Expand Up @@ -155,7 +156,7 @@ const SessionReplayOnboarding = (): JSX.Element => {
const { currentTeam } = useValues(teamLogic)

const { featureFlags } = useValues(featureFlagLogic)
const hasAndroidOnBoarding = !!featureFlags[FEATURE_FLAGS.SESSION_REPLAY_MOBILE_ONBOARDING]
const hasMobileOnBoarding = !!featureFlags[FEATURE_FLAGS.SESSION_REPLAY_MOBILE_ONBOARDING]

const configOptions: ProductConfigOption[] = [
{
Expand Down Expand Up @@ -192,8 +193,9 @@ const SessionReplayOnboarding = (): JSX.Element => {
}

const sdkInstructionMap = SessionReplaySDKInstructions
if (hasAndroidOnBoarding) {
if (hasMobileOnBoarding) {
sdkInstructionMap[SDKKey.ANDROID] = AndroidInstructions
sdkInstructionMap[SDKKey.IOS] = iOSInstructions
}

return (
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/scenes/onboarding/sdks/feature-flags/ios.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { FlaggedFeature } from 'lib/components/FlaggedFeature'
import { FEATURE_FLAGS } from 'lib/constants'
import { AdvertiseiOSReplay } from 'scenes/onboarding/sdks/product-analytics'

import { SDKKey } from '~/types'

import { SDKInstallIOSInstructions } from '../sdk-install-instructions'
Expand All @@ -8,6 +12,9 @@ export function FeatureFlagsIOSInstructions(): JSX.Element {
<>
<SDKInstallIOSInstructions />
<FlagImplementationSnippet sdkKey={SDKKey.IOS} />
<FlaggedFeature flag={FEATURE_FLAGS.SESSION_REPLAY_MOBILE_ONBOARDING} match={true}>
<AdvertiseiOSReplay context="product-analytics-onboarding" />
</FlaggedFeature>
</>
)
}
39 changes: 39 additions & 0 deletions frontend/src/scenes/onboarding/sdks/product-analytics/ios.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
import { CodeSnippet, Language } from 'lib/components/CodeSnippet'
import { FlaggedFeature } from 'lib/components/FlaggedFeature'
import { FEATURE_FLAGS } from 'lib/constants'
import { LemonBanner } from 'lib/lemon-ui/LemonBanner'
import { LemonDivider } from 'lib/lemon-ui/LemonDivider'
import { LemonTag } from 'lib/lemon-ui/LemonTag'
import { Link } from 'lib/lemon-ui/Link'
import { OnboardingStepKey } from 'scenes/onboarding/onboardingLogic'
import { urls } from 'scenes/urls'

import { SDKKey } from '~/types'

import { SDKInstallIOSInstructions } from '../sdk-install-instructions'
import { PersonModeEventPropertyInstructions } from '../shared-snippets'
Expand All @@ -7,13 +17,42 @@ function IOSCaptureSnippet(): JSX.Element {
return <CodeSnippet language={Language.Swift}>{`PostHogSDK.shared.capture("Test Event")`}</CodeSnippet>
}

export function AdvertiseiOSReplay({
context,
}: {
context: 'product-analytics-onboarding' | 'flags-onboarding'
}): JSX.Element {
return (
<div>
<LemonDivider className="my-8" />
<LemonBanner type="info">
<h3>
Session Replay for iOS <LemonTag type="highlight">NEW</LemonTag>
</h3>
<div>
Session replay is now in beta for iOS.{' '}
<Link
to={urls.onboarding('session_replay', OnboardingStepKey.INSTALL, SDKKey.IOS)}
data-attr={`${context}-ios-replay-cta`}
>
Learn how to set it up
</Link>
</div>
</LemonBanner>
</div>
)
}

export function ProductAnalyticsIOSInstructions(): JSX.Element {
return (
<>
<SDKInstallIOSInstructions />
<h3>Send an event</h3>
<IOSCaptureSnippet />
<PersonModeEventPropertyInstructions />
<FlaggedFeature flag={FEATURE_FLAGS.SESSION_REPLAY_MOBILE_ONBOARDING} match={true}>
<AdvertiseiOSReplay context="product-analytics-onboarding" />
</FlaggedFeature>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,17 @@ function AndroidSetupSnippet({ includeReplay }: AndroidSetupProps): JSX.Element
config.sessionReplay = true
// choose whether to mask images or text
config.sessionReplayConfig.maskAllImages = false
config.sessionReplayConfig.maskAllTextInputs = true`
config.sessionReplayConfig.maskAllTextInputs = true
// screenshot is disabled by default
// The screenshot may contain sensitive information, use with caution
config.sessionReplayConfig.screenshot = true`
: ''
}

// Setup PostHog with the given Context and Config
PostHogAndroid.setup(this, config)
}`}
}
}`}
</CodeSnippet>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { LemonBanner, Link } from '@posthog/lemon-ui'
import { useValues } from 'kea'
import { CodeSnippet, Language } from 'lib/components/CodeSnippet'
import { apiHostOrigin } from 'lib/utils/apiHost'
import { teamLogic } from 'scenes/teamLogic'

export interface iOSSetupProps {
includeReplay?: boolean
}

function IOSInstallCocoaPodsSnippet(): JSX.Element {
return <CodeSnippet language={Language.Ruby}>{'pod "PostHog", "~> 3.0.0"'}</CodeSnippet>
}
Expand All @@ -17,7 +22,7 @@ function IOSInstallSPMSnippet(): JSX.Element {
)
}

function IOSSetupSnippet(): JSX.Element {
function IOSSetupSnippet({ includeReplay }: iOSSetupProps): JSX.Element {
const { currentTeam } = useValues(teamLogic)

return (
Expand All @@ -32,6 +37,21 @@ class AppDelegate: NSObject, UIApplicationDelegate {
let POSTHOG_HOST = "${apiHostOrigin()}"

let config = PostHogConfig(apiKey: POSTHOG_API_KEY, host: POSTHOG_HOST)
${
includeReplay
? `
// check https://posthog.com/docs/session-replay/mobile#installation
// for more config and to learn about how we capture sessions on mobile
// and what to expect
config.sessionReplay = true
// choose whether to mask images or text
config.sessionReplayConfig.maskAllImages = false
config.sessionReplayConfig.maskAllTextInputs = true
// screenshot is disabled by default
// The screenshot may contain sensitive information, use with caution
config.sessionReplayConfig.screenshotMode = true`
: ''
}
PostHogSDK.shared.setup(config)

return true
Expand All @@ -41,15 +61,26 @@ class AppDelegate: NSObject, UIApplicationDelegate {
)
}

export function SDKInstallIOSInstructions(): JSX.Element {
export function SDKInstallIOSInstructions(props: iOSSetupProps): JSX.Element {
return (
<>
{props.includeReplay ? (
<LemonBanner type="info">
🚧 NOTE: <Link to="https://posthog.com/docs/session-replay/mobile">Mobile recording</Link> is
currently in beta. We are keen to gather as much feedback as possible so if you try this out please
let us know. You can send feedback via the{' '}
<Link to="https://us.posthog.com/#panel=support%3Afeedback%3Asession_replay%3Alow">
in-app support panel
</Link>{' '}
or one of our other <Link to="https://posthog.com/docs/support-options">support options</Link>.
</LemonBanner>
) : null}
<h3>Install via CocoaPods</h3>
<IOSInstallCocoaPodsSnippet />
<h3>Or Install via SPM</h3>
<IOSInstallSPMSnippet />
<h3>Configure</h3>
<IOSSetupSnippet />
<IOSSetupSnippet {...props} />
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from './astro'
export * from './bubble'
export * from './framer'
export * from './html-snippet'
export * from './ios'
export * from './js-web'
export * from './next-js'
export * from './nuxt'
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/scenes/onboarding/sdks/session-replay/ios.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { SDKInstallIOSInstructions } from '../sdk-install-instructions'
import { SessionReplayFinalSteps } from '../shared-snippets'

export function iOSInstructions(): JSX.Element {
return (
<>
<SDKInstallIOSInstructions includeReplay={true} />
<SessionReplayFinalSteps />
</>
)
}
Loading