Merge pull request #33805 from overleaf/mg-ai-paywall-analytics
Add paywall-prompt and paywall-click events to ai paywalls GitOrigin-RevId: aa7de15a990ad1833e3dda65d5fb50f60bb7c9e3
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import { useEffect } from 'react'
|
||||
import Notification from '@/shared/components/notification'
|
||||
import UpgradeButton from '@/features/ide-react/components/toolbar/upgrade-button'
|
||||
import PaywallUpgradeButton from '@/shared/components/paywall-upgrade-button'
|
||||
import { useEditorContext } from '@/shared/context/editor-context'
|
||||
import { useUserFeaturesContext } from '@/shared/context/user-features-context'
|
||||
import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { formatSecondsToHoursAndMinutes } from '@/shared/utils/time'
|
||||
import { useFeatureFlag } from '@/shared/context/split-test-context'
|
||||
@@ -9,14 +11,20 @@ import { useFeatureFlag } from '@/shared/context/split-test-context'
|
||||
import getMeta from '@/utils/meta'
|
||||
const hasUnlimitedAi = getMeta('ol-hasUnlimitedAi')
|
||||
|
||||
type aiFeatureLocations = 'errorAssist' | 'workbench'
|
||||
type AiFeatureLocations = 'errorAssist' | 'workbench'
|
||||
type PaywallType = 'assistant' | 'workbench'
|
||||
|
||||
const paywallTypeByLocation: Record<AiFeatureLocations, PaywallType> = {
|
||||
workbench: 'workbench',
|
||||
errorAssist: 'assistant',
|
||||
}
|
||||
|
||||
function AiPaywallNotification({
|
||||
isActionBelowContent = false,
|
||||
featureLocation,
|
||||
}: {
|
||||
isActionBelowContent?: boolean
|
||||
featureLocation: aiFeatureLocations
|
||||
featureLocation: AiFeatureLocations
|
||||
}) {
|
||||
const {
|
||||
hasSuggestionsLeft,
|
||||
@@ -123,29 +131,12 @@ function AiPaywallNotification({
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const message = t('upgrade_for_unlimited_access_to_ai', {
|
||||
time: formatSecondsToHoursAndMinutes(t, secondsTillReset),
|
||||
})
|
||||
return (
|
||||
<>
|
||||
<Notification
|
||||
type="info"
|
||||
title={t('youve_hit_your_daily_ai_limit')}
|
||||
content={message}
|
||||
isDismissible={false}
|
||||
customIcon={null}
|
||||
isActionBelowContent={isActionBelowContent}
|
||||
action={
|
||||
<UpgradeButton
|
||||
className="px-2.5 py-2"
|
||||
referrer="ai"
|
||||
source={featureLocation}
|
||||
/>
|
||||
}
|
||||
className="ai-upgrade-paywall-btn ai-paywall-notification"
|
||||
/>
|
||||
</>
|
||||
<UpgradePaywall
|
||||
secondsTillReset={secondsTillReset}
|
||||
isActionBelowContent={isActionBelowContent}
|
||||
featureLocation={featureLocation}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -154,7 +145,7 @@ function GroupsPaywall({
|
||||
featureLocation,
|
||||
}: {
|
||||
secondsTillReset: number
|
||||
featureLocation: aiFeatureLocations
|
||||
featureLocation: AiFeatureLocations
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@@ -186,7 +177,7 @@ function CommonsPaywall({
|
||||
featureLocation,
|
||||
}: {
|
||||
secondsTillReset: number
|
||||
featureLocation: aiFeatureLocations
|
||||
featureLocation: AiFeatureLocations
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@@ -218,7 +209,7 @@ function FairUseLimit({
|
||||
featureLocation,
|
||||
}: {
|
||||
secondsTillReset: number
|
||||
featureLocation: aiFeatureLocations
|
||||
featureLocation: AiFeatureLocations
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@@ -254,4 +245,45 @@ function FairUseLimit({
|
||||
)
|
||||
}
|
||||
|
||||
function UpgradePaywall({
|
||||
secondsTillReset,
|
||||
isActionBelowContent,
|
||||
featureLocation,
|
||||
}: {
|
||||
secondsTillReset: number
|
||||
isActionBelowContent: boolean
|
||||
featureLocation: AiFeatureLocations
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
const { sendEvent } = useEditorAnalytics()
|
||||
const paywallType = paywallTypeByLocation[featureLocation]
|
||||
|
||||
useEffect(() => {
|
||||
sendEvent('paywall-prompt', {
|
||||
'paywall-type': paywallType,
|
||||
})
|
||||
}, [sendEvent, paywallType])
|
||||
|
||||
return (
|
||||
<Notification
|
||||
type="info"
|
||||
title={t('youve_hit_your_daily_ai_limit')}
|
||||
content={t('upgrade_for_unlimited_access_to_ai', {
|
||||
time: formatSecondsToHoursAndMinutes(t, secondsTillReset),
|
||||
})}
|
||||
isDismissible={false}
|
||||
customIcon={null}
|
||||
isActionBelowContent={isActionBelowContent}
|
||||
action={
|
||||
<PaywallUpgradeButton
|
||||
referrer="ai"
|
||||
paywallType={paywallType}
|
||||
className="px-2.5 py-2"
|
||||
/>
|
||||
}
|
||||
className="ai-upgrade-paywall-btn ai-paywall-notification"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default AiPaywallNotification
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export default function PaywallUpgradeButton({
|
||||
referrer,
|
||||
paywallType,
|
||||
className,
|
||||
}: {
|
||||
referrer: string
|
||||
paywallType: string
|
||||
className?: string
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
const { sendEvent } = useEditorAnalytics()
|
||||
const user = getMeta('ol-user')
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
sendEvent('paywall-click', {
|
||||
upgradeType: user.hasPaidSubscription ? 'add-on' : 'standalone',
|
||||
'paywall-type': paywallType,
|
||||
})
|
||||
}, [sendEvent, user.hasPaidSubscription, paywallType])
|
||||
|
||||
return (
|
||||
<OLButton
|
||||
variant="premium"
|
||||
size="sm"
|
||||
href={`/user/subscription/choose-your-plan?itm_referrer=${referrer}&itm_campaign=${paywallType}`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={className}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{t('upgrade')}
|
||||
</OLButton>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user