Merge pull request #12811 from overleaf/jk-plans-event-currency-segmentation

[web] Add currency/id segmentation to Recurly analytics events

GitOrigin-RevId: 56998f403358d5f6b3cece6835e16e65e06635b1
This commit is contained in:
June Kelly 2023-05-02 13:45:55 +01:00 committed by Copybot
parent 5480e1b371
commit e89b4b4214
5 changed files with 94 additions and 15 deletions

View file

@ -2,6 +2,8 @@ const AnalyticsManager = require('../Analytics/AnalyticsManager')
const SubscriptionEmailHandler = require('./SubscriptionEmailHandler') const SubscriptionEmailHandler = require('./SubscriptionEmailHandler')
const { ObjectID } = require('mongodb') const { ObjectID } = require('mongodb')
const INVOICE_SUBSCRIPTION_LIMIT = 10
async function sendRecurlyAnalyticsEvent(event, eventData) { async function sendRecurlyAnalyticsEvent(event, eventData) {
const userId = _getUserId(eventData) const userId = _getUserId(eventData)
if (!ObjectID.isValid(userId)) { if (!ObjectID.isValid(userId)) {
@ -47,11 +49,13 @@ async function sendRecurlyAnalyticsEvent(event, eventData) {
} }
async function _sendSubscriptionStartedEvent(userId, eventData) { async function _sendSubscriptionStartedEvent(userId, eventData) {
const { planCode, quantity, state, isTrial } = _getSubscriptionData(eventData) const { planCode, quantity, state, isTrial, subscriptionId } =
_getSubscriptionData(eventData)
AnalyticsManager.recordEventForUser(userId, 'subscription-started', { AnalyticsManager.recordEventForUser(userId, 'subscription-started', {
plan_code: planCode, plan_code: planCode,
quantity, quantity,
is_trial: isTrial, is_trial: isTrial,
subscriptionId,
}) })
AnalyticsManager.setUserPropertyForUser( AnalyticsManager.setUserPropertyForUser(
userId, userId,
@ -71,11 +75,13 @@ async function _sendSubscriptionStartedEvent(userId, eventData) {
} }
async function _sendSubscriptionUpdatedEvent(userId, eventData) { async function _sendSubscriptionUpdatedEvent(userId, eventData) {
const { planCode, quantity, state, isTrial } = _getSubscriptionData(eventData) const { planCode, quantity, state, isTrial, subscriptionId } =
_getSubscriptionData(eventData)
AnalyticsManager.recordEventForUser(userId, 'subscription-updated', { AnalyticsManager.recordEventForUser(userId, 'subscription-updated', {
plan_code: planCode, plan_code: planCode,
quantity, quantity,
is_trial: isTrial, is_trial: isTrial,
subscriptionId,
}) })
AnalyticsManager.setUserPropertyForUser( AnalyticsManager.setUserPropertyForUser(
userId, userId,
@ -91,11 +97,13 @@ async function _sendSubscriptionUpdatedEvent(userId, eventData) {
} }
async function _sendSubscriptionCancelledEvent(userId, eventData) { async function _sendSubscriptionCancelledEvent(userId, eventData) {
const { planCode, quantity, state, isTrial } = _getSubscriptionData(eventData) const { planCode, quantity, state, isTrial, subscriptionId } =
_getSubscriptionData(eventData)
AnalyticsManager.recordEventForUser(userId, 'subscription-cancelled', { AnalyticsManager.recordEventForUser(userId, 'subscription-cancelled', {
plan_code: planCode, plan_code: planCode,
quantity, quantity,
is_trial: isTrial, is_trial: isTrial,
subscriptionId,
}) })
AnalyticsManager.setUserPropertyForUser(userId, 'subscription-state', state) AnalyticsManager.setUserPropertyForUser(userId, 'subscription-state', state)
AnalyticsManager.setUserPropertyForUser( AnalyticsManager.setUserPropertyForUser(
@ -106,11 +114,13 @@ async function _sendSubscriptionCancelledEvent(userId, eventData) {
} }
async function _sendSubscriptionExpiredEvent(userId, eventData) { async function _sendSubscriptionExpiredEvent(userId, eventData) {
const { planCode, quantity, state, isTrial } = _getSubscriptionData(eventData) const { planCode, quantity, state, isTrial, subscriptionId } =
_getSubscriptionData(eventData)
AnalyticsManager.recordEventForUser(userId, 'subscription-expired', { AnalyticsManager.recordEventForUser(userId, 'subscription-expired', {
plan_code: planCode, plan_code: planCode,
quantity, quantity,
is_trial: isTrial, is_trial: isTrial,
subscriptionId,
}) })
AnalyticsManager.setUserPropertyForUser( AnalyticsManager.setUserPropertyForUser(
userId, userId,
@ -126,11 +136,13 @@ async function _sendSubscriptionExpiredEvent(userId, eventData) {
} }
async function _sendSubscriptionRenewedEvent(userId, eventData) { async function _sendSubscriptionRenewedEvent(userId, eventData) {
const { planCode, quantity, state, isTrial } = _getSubscriptionData(eventData) const { planCode, quantity, state, isTrial, subscriptionId } =
_getSubscriptionData(eventData)
AnalyticsManager.recordEventForUser(userId, 'subscription-renewed', { AnalyticsManager.recordEventForUser(userId, 'subscription-renewed', {
plan_code: planCode, plan_code: planCode,
quantity, quantity,
is_trial: isTrial, is_trial: isTrial,
subscriptionId,
}) })
AnalyticsManager.setUserPropertyForUser( AnalyticsManager.setUserPropertyForUser(
userId, userId,
@ -146,10 +158,12 @@ async function _sendSubscriptionRenewedEvent(userId, eventData) {
} }
async function _sendSubscriptionReactivatedEvent(userId, eventData) { async function _sendSubscriptionReactivatedEvent(userId, eventData) {
const { planCode, quantity, state, isTrial } = _getSubscriptionData(eventData) const { planCode, quantity, state, isTrial, subscriptionId } =
_getSubscriptionData(eventData)
AnalyticsManager.recordEventForUser(userId, 'subscription-reactivated', { AnalyticsManager.recordEventForUser(userId, 'subscription-reactivated', {
plan_code: planCode, plan_code: planCode,
quantity, quantity,
subscriptionId,
}) })
AnalyticsManager.setUserPropertyForUser( AnalyticsManager.setUserPropertyForUser(
userId, userId,
@ -165,7 +179,35 @@ async function _sendSubscriptionReactivatedEvent(userId, eventData) {
} }
async function _sendInvoicePaidEvent(userId, eventData) { async function _sendInvoicePaidEvent(userId, eventData) {
AnalyticsManager.recordEventForUser(userId, 'subscription-invoice-collected') const invoice = eventData.invoice
if (!invoice) {
return
}
const invoiceNumber = invoice.invoice_number
const currency = invoice.currency
const totalInCents = invoice.total_in_cents
const taxInCents = invoice.tax_in_cents
const country = invoice.address?.country
const collectionMethod = invoice.collection_method
const subscriptionIds = {}
invoice.subscription_ids?.forEach((e, idx) => {
if (idx < INVOICE_SUBSCRIPTION_LIMIT) {
subscriptionIds[`subscriptionId${idx + 1}`] = e
}
})
AnalyticsManager.recordEventForUser(
userId,
'subscription-invoice-collected',
{
invoiceNumber,
currency,
totalInCents,
taxInCents,
country,
collectionMethod,
...subscriptionIds,
}
)
AnalyticsManager.setUserPropertyForUser( AnalyticsManager.setUserPropertyForUser(
userId, userId,
'subscription-is-trial', 'subscription-is-trial',
@ -195,6 +237,7 @@ function _getSubscriptionData(eventData) {
planCode: eventData.subscription.plan.plan_code, planCode: eventData.subscription.plan.plan_code,
quantity: eventData.subscription.quantity, quantity: eventData.subscription.quantity,
state: eventData.subscription.state, state: eventData.subscription.state,
subscriptionId: eventData.subscription.uuid,
isTrial, isTrial,
} }
} }

View file

@ -69,7 +69,9 @@ async function plansPage(req, res) {
usage: getDefault('usage', 'usage', 'enterprise'), usage: getDefault('usage', 'usage', 'enterprise'),
} }
AnalyticsManager.recordEventForSession(req.session, 'plans-page-view') AnalyticsManager.recordEventForSession(req.session, 'plans-page-view', {
currency: recommendedCurrency,
})
res.render('subscriptions/plans-marketing-v2', { res.render('subscriptions/plans-marketing-v2', {
title: 'plans_and_pricing', title: 'plans_and_pricing',

View file

@ -95,7 +95,10 @@ function usePayment({ publicKey }: RecurlyOptions) {
return return
} }
eventTracking.sendMB('payment-page-view', { plan: planCode }) eventTracking.sendMB('payment-page-view', {
plan: planCode,
currency: currencyCode,
})
eventTracking.send( eventTracking.send(
'subscription-funnel', 'subscription-funnel',
'subscription-form-viewed', 'subscription-form-viewed',
@ -147,6 +150,7 @@ function usePayment({ publicKey }: RecurlyOptions) {
initiallySelectedCurrencyCode, initiallySelectedCurrencyCode,
planCode, planCode,
publicKey, publicKey,
currencyCode,
t, t,
]) ])

View file

@ -76,7 +76,10 @@ export default App.controller(
`&itm_referrer=${window.ITMReferrer}` `&itm_referrer=${window.ITMReferrer}`
} }
eventTracking.sendMB('payment-page-view', { plan: window.plan_code }) eventTracking.sendMB('payment-page-view', {
plan: window.plan_code,
currency: $scope.currencyCode,
})
eventTracking.send( eventTracking.send(
'subscription-funnel', 'subscription-funnel',
'subscription-form-viewed', 'subscription-form-viewed',

View file

@ -12,6 +12,7 @@ describe('RecurlyEventHandler', function () {
account_code: this.userId, account_code: this.userId,
}, },
subscription: { subscription: {
uuid: '8435ad98c1ce45da99b07f6a6a2e780f',
plan: { plan: {
plan_code: 'collaborator-annual', plan_code: 'collaborator-annual',
}, },
@ -50,6 +51,7 @@ describe('RecurlyEventHandler', function () {
plan_code: this.planCode, plan_code: this.planCode,
quantity: 1, quantity: 1,
is_trial: true, is_trial: true,
subscriptionId: this.eventData.subscription.uuid,
} }
) )
sinon.assert.calledWith( sinon.assert.calledWith(
@ -102,6 +104,7 @@ describe('RecurlyEventHandler', function () {
plan_code: this.planCode, plan_code: this.planCode,
quantity: 3, quantity: 3,
is_trial: false, is_trial: false,
subscriptionId: this.eventData.subscription.uuid,
} }
) )
sinon.assert.calledWith( sinon.assert.calledWith(
@ -133,6 +136,7 @@ describe('RecurlyEventHandler', function () {
plan_code: this.planCode, plan_code: this.planCode,
quantity: 1, quantity: 1,
is_trial: true, is_trial: true,
subscriptionId: this.eventData.subscription.uuid,
} }
) )
sinon.assert.calledWith( sinon.assert.calledWith(
@ -169,6 +173,7 @@ describe('RecurlyEventHandler', function () {
plan_code: this.planCode, plan_code: this.planCode,
quantity: 1, quantity: 1,
is_trial: true, is_trial: true,
subscriptionId: this.eventData.subscription.uuid,
} }
) )
sinon.assert.calledWith( sinon.assert.calledWith(
@ -199,6 +204,7 @@ describe('RecurlyEventHandler', function () {
plan_code: this.planCode, plan_code: this.planCode,
quantity: 1, quantity: 1,
is_trial: true, is_trial: true,
subscriptionId: this.eventData.subscription.uuid,
} }
) )
sinon.assert.calledWith( sinon.assert.calledWith(
@ -234,6 +240,7 @@ describe('RecurlyEventHandler', function () {
plan_code: this.planCode, plan_code: this.planCode,
quantity: 1, quantity: 1,
is_trial: true, is_trial: true,
subscriptionId: this.eventData.subscription.uuid,
} }
) )
}) })
@ -250,27 +257,47 @@ describe('RecurlyEventHandler', function () {
{ {
plan_code: this.planCode, plan_code: this.planCode,
quantity: 1, quantity: 1,
subscriptionId: this.eventData.subscription.uuid,
} }
) )
}) })
it('with paid_charge_invoice_notification', function () { it('with paid_charge_invoice_notification', function () {
const invoice = {
invoice_number: 1234,
currency: 'USD',
state: 'paid',
total_in_cents: 720,
tax_in_cents: 12,
address: {
country: 'Liurnia',
},
collection_method: 'automatic',
subscription_ids: ['abcd1234', 'defa3214'],
}
this.RecurlyEventHandler.sendRecurlyAnalyticsEvent( this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
'paid_charge_invoice_notification', 'paid_charge_invoice_notification',
{ {
account: { account: {
account_code: this.userId, account_code: this.userId,
}, },
invoice: { invoice,
state: 'paid',
total_in_cents: 720,
},
} }
) )
sinon.assert.calledWith( sinon.assert.calledWith(
this.AnalyticsManager.recordEventForUser, this.AnalyticsManager.recordEventForUser,
this.userId, this.userId,
'subscription-invoice-collected' 'subscription-invoice-collected',
{
invoiceNumber: invoice.invoice_number,
currency: invoice.currency,
totalInCents: invoice.total_in_cents,
taxInCents: invoice.tax_in_cents,
country: invoice.address.country,
collectionMethod: invoice.collection_method,
subscriptionId1: invoice.subscription_ids[0],
subscriptionId2: invoice.subscription_ids[1],
}
) )
}) })