Merge pull request #32611 from overleaf/rh-cio-email-sdk

Add identifiers to cio calls to avoid profile splits

GitOrigin-RevId: fec8cad4e87f8df910d729bd00acbf26d0931102
This commit is contained in:
roo hutton
2026-04-10 10:54:11 +01:00
committed by Copybot
parent 78c81cd0d5
commit 24b16c1304
3 changed files with 28 additions and 5 deletions

View File

@@ -42,6 +42,7 @@ async function refreshFeatures(userId, reason) {
const user = await UserGetter.promises.getUser(userId, {
_id: 1,
features: 1,
email: 1,
})
const oldFeatures = _.clone(user.features)
const features = await computeFeatures(userId)
@@ -57,14 +58,14 @@ async function refreshFeatures(userId, reason) {
const { features: newFeatures, featuresChanged } =
await UserFeaturesUpdater.promises.updateFeatures(userId, features)
// TODO: this call is quite expensive, so ideally we'd update cio with something
// that doesn't require the best subscription to be computed, ie. the plan code (or type)
const bestSubscriptionType = await _getBestSubscriptionType(userId)
Modules.promises.hooks
.fire('setUserProperties', userId, {
features,
'best-subscription-type': bestSubscriptionType,
overleafId: userId,
...(user.email && { email: user.email }),
})
.catch(err => {
logger.error({ err, userId }, 'Failed to sync features to customer.io')

View File

@@ -1,8 +1,9 @@
if(customerIoEnabled && ExposedSettings.cioWriteKey && ExposedSettings.cioSiteId)
script(type="text/javascript", id="cio-loader", nonce=scriptNonce, data-cio-write-key=ExposedSettings.cioWriteKey, data-cio-site-id=ExposedSettings.cioSiteId, data-session-analytics-id=getSessionAnalyticsId(), data-user-id=((user && user._id) || '')).
script(type="text/javascript", id="cio-loader", nonce=scriptNonce, data-cio-write-key=ExposedSettings.cioWriteKey, data-cio-site-id=ExposedSettings.cioSiteId, data-session-analytics-id=getSessionAnalyticsId(), data-user-id=((user && user._id) || ''), data-user-email=((user && user.email) || '')).
var cioSettings = document.querySelector('#cio-loader').dataset;
var analyticsId = cioSettings.sessionAnalyticsId;
var userId = cioSettings.userId;
var userEmail = cioSettings.userEmail;
var siteId = cioSettings.cioSiteId;
var writeKey = cioSettings.cioWriteKey;
@@ -22,6 +23,6 @@ if(customerIoEnabled && ExposedSettings.cioWriteKey && ExposedSettings.cioSiteId
analytics.setAnonymousId(analyticsId);
}
if (userId) {
analytics.identify(userId);
};
analytics.identify(userId, userEmail ? { email: userEmail } : {});
}
}}();

View File

@@ -426,6 +426,27 @@ describe('FeaturesUpdater', function () {
{
features: ctx.Settings.features.all,
'best-subscription-type': 'individual',
overleafId: ctx.user._id,
}
)
})
})
describe('when user has an email', function () {
beforeEach(async function (ctx) {
ctx.user.email = 'user@example.com'
await ctx.FeaturesUpdater.promises.refreshFeatures(ctx.user._id, 'test')
})
it('should include email in customer.io properties', function (ctx) {
expect(ctx.Modules.promises.hooks.fire).to.have.been.calledWith(
'setUserProperties',
ctx.user._id,
{
features: ctx.Settings.features.all,
'best-subscription-type': 'individual',
overleafId: ctx.user._id,
email: 'user@example.com',
}
)
})