Add geo-pricing split test for enabling LATAM currencies (#13663)

* Implement LATAM geo-pricing split test

* Hide Paypal if currency is one of INR, COP, CLP, PEN

* Only send the LATAM/INR banner events when banner is rendered

* Workaround in Subscription dashboard for CLP not having minor units

GitOrigin-RevId: a677086a7762900563558126d2f81a4c57bbe9d7
This commit is contained in:
Thomas
2023-07-17 11:01:10 +00:00
committed by Copybot
parent 8efac32c8a
commit c1ec3044d7
12 changed files with 239 additions and 25 deletions
@@ -364,7 +364,11 @@ async function projectListPage(req, res, next) {
}
let showINRBanner = false
let showLATAMBanner = false
let recommendedCurrency
if (usersBestSubscription?.type === 'free') {
const { currencyCode, countryCode } =
await GeoIpLookup.promises.getCurrencyCode(req.ip)
try {
const inrGeoPricingAssignment =
await SplitTestHandler.promises.getAssignment(
@@ -372,14 +376,32 @@ async function projectListPage(req, res, next) {
res,
'geo-pricing-inr'
)
const geoDetails = await GeoIpLookup.promises.getDetails(req.ip)
showINRBanner =
inrGeoPricingAssignment.variant === 'inr' &&
geoDetails?.country_code === 'IN'
inrGeoPricingAssignment.variant === 'inr' && countryCode === 'IN'
} catch (error) {
logger.error(
{ err: error },
'Failed to get INR geo pricing lookup or assignment'
'Failed to get geo-pricing-inr split test assignment'
)
}
try {
const latamGeoPricingAssignment =
await SplitTestHandler.promises.getAssignment(
req,
res,
'geo-pricing-latam'
)
showLATAMBanner =
latamGeoPricingAssignment.variant === 'latam' &&
['BR', 'MX', 'CO', 'CL', 'PE'].includes(countryCode)
// LATAM Banner needs to know which currency to display
if (showLATAMBanner) {
recommendedCurrency = currencyCode
}
} catch (error) {
logger.error(
{ err: error },
'Failed to get geo-pricing-latam split test assignment'
)
}
}
@@ -402,6 +424,8 @@ async function projectListPage(req, res, next) {
groupsAndEnterpriseBannerVariant,
showWritefullPromoBanner,
showINRBanner,
showLATAMBanner,
recommendedCurrency,
projectDashboardReact: true, // used in navbar
welcomePageRedesignVariant: welcomePageRedesignAssignment.variant,
groupSubscriptionsPendingEnrollment:
@@ -58,8 +58,12 @@ async function plansPage(req, res) {
if (GeoIpLookup.isValidCurrencyParam(queryCurrency)) {
currency = queryCurrency
}
const { recommendedCurrency, countryCode, geoPricingTestVariant } =
await _getRecommendedCurrency(req, res)
const {
recommendedCurrency,
countryCode,
geoPricingINRTestVariant,
geoPricingLATAMTestVariant,
} = await _getRecommendedCurrency(req, res)
if (recommendedCurrency && currency == null) {
currency = recommendedCurrency
}
@@ -108,8 +112,14 @@ async function plansPage(req, res) {
currency: recommendedCurrency,
'remove-personal-plan-page': removePersonalPlanAssingment?.variant,
countryCode,
'geo-pricing-inr-group': geoPricingTestVariant,
'geo-pricing-inr-group': geoPricingINRTestVariant,
'geo-pricing-inr-page': currency === 'INR' ? 'inr' : 'default',
'geo-pricing-latam-group': geoPricingLATAMTestVariant,
'geo-pricing-latam-page': ['BRL', 'MXN', 'COP', 'CLP', 'PEN'].includes(
currency
)
? 'latam'
: 'default',
})
res.render(`subscriptions/plans-marketing/${directory}/plans-marketing-v2`, {
@@ -264,8 +274,12 @@ async function userSubscriptionPage(req, res) {
async function interstitialPaymentPage(req, res) {
const user = SessionManager.getSessionUser(req.session)
const { recommendedCurrency, countryCode, geoPricingTestVariant } =
await _getRecommendedCurrency(req, res)
const {
recommendedCurrency,
countryCode,
geoPricingINRTestVariant,
geoPricingLATAMTestVariant,
} = await _getRecommendedCurrency(req, res)
const hasSubscription =
await LimitationsManager.promises.userHasV1OrV2Subscription(user)
@@ -300,9 +314,15 @@ async function interstitialPaymentPage(req, res) {
{
currency: recommendedCurrency,
countryCode,
'geo-pricing-inr-group': geoPricingTestVariant,
'geo-pricing-inr-group': geoPricingINRTestVariant,
'geo-pricing-inr-page':
recommendedCurrency === 'INR' ? 'inr' : 'default',
'geo-pricing-latam-group': geoPricingLATAMTestVariant,
'geo-pricing-latam-page': ['BRL', 'MXN', 'COP', 'CLP', 'PEN'].includes(
recommendedCurrency
)
? 'latam'
: 'default',
'remove-personal-plan-page': removePersonalPlanAssingment?.variant,
}
)
@@ -665,10 +685,10 @@ async function _getRecommendedCurrency(req, res) {
)
const countryCode = currencyLookup.countryCode
let recommendedCurrency = currencyLookup.currencyCode
let assignment
let assignmentINR, assignmentLATAM
// for #12703
try {
assignment = await SplitTestHandler.promises.getAssignment(
assignmentINR = await SplitTestHandler.promises.getAssignment(
req,
res,
'geo-pricing-inr'
@@ -679,15 +699,35 @@ async function _getRecommendedCurrency(req, res) {
'Failed to get assignment for geo-pricing-inr test'
)
}
// for #13559
try {
assignmentLATAM = await SplitTestHandler.promises.getAssignment(
req,
res,
'geo-pricing-latam'
)
} catch (error) {
logger.error(
{ err: error },
'Failed to get assignment for geo-pricing-latam test'
)
}
// if the user has been detected as located in India (thus recommended INR as currency)
// but is not part of the geo pricing test, we fall back to the default currency instead
if (recommendedCurrency === 'INR' && assignment?.variant !== 'inr') {
if (recommendedCurrency === 'INR' && assignmentINR?.variant !== 'inr') {
recommendedCurrency = GeoIpLookup.DEFAULT_CURRENCY_CODE
}
if (
['BRL', 'MXN', 'COP', 'CLP', 'PEN'].includes(recommendedCurrency) &&
assignmentLATAM?.variant !== 'latam'
) {
recommendedCurrency = GeoIpLookup.DEFAULT_CURRENCY_CODE
}
return {
recommendedCurrency,
countryCode,
geoPricingTestVariant: assignment?.variant,
geoPricingINRTestVariant: assignmentINR?.variant,
geoPricingLATAMTestVariant: assignmentLATAM?.variant,
}
}
@@ -13,12 +13,24 @@ const currencySymbols = {
CHF: 'Fr',
SGD: '$',
INR: '₹',
BRL: 'R$',
MXN: '$',
COP: '$',
CLP: '$',
PEN: 'S/',
}
module.exports = {
formatPrice(priceInCents, currency) {
if (!currency) {
currency = 'USD'
} else if (currency === 'CLP') {
// CLP doesn't have minor units, recurly stores the whole major unit without cents
return priceInCents.toLocaleString('es-CL', {
style: 'currency',
currency,
minimumFractionDigits: 0,
})
}
let string = String(Math.round(priceInCents))
if (string.length === 2) {
@@ -19,11 +19,21 @@ const currencyMappings = {
SE: 'SEK',
SG: 'SGD',
IN: 'INR',
BR: 'BRL',
MX: 'MXN',
CO: 'COP',
CL: 'CLP',
PE: 'PEN',
}
const validCurrencyParams = Object.values(currencyMappings).concat([
'EUR',
'INR',
'BRL',
'MXN',
'COP',
'CLP',
'PEN',
])
// Countries which would likely prefer Euro's
@@ -29,6 +29,8 @@ block append meta
meta(name="ol-showWritefullPromoBanner" data-type="boolean" content=showWritefullPromoBanner)
meta(name="ol-groupsAndEnterpriseBannerVariant" data-type="string" content=groupsAndEnterpriseBannerVariant)
meta(name="ol-showINRBanner" data-type="boolean" content=showINRBanner)
meta(name="ol-showLATAMBanner" data-type="boolean" content=showLATAMBanner)
meta(name="ol-recommendedCurrency" data-type="string" content=recommendedCurrency)
meta(name="ol-welcomePageRedesignVariant" data-type="string" content=welcomePageRedesignVariant)
meta(name="ol-groupSubscriptionsPendingEnrollment" data-type="json" content=groupSubscriptionsPendingEnrollment)