mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-29 05:13:43 -05:00
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:
parent
5480e1b371
commit
e89b4b4214
5 changed files with 94 additions and 15 deletions
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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],
|
||||||
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue