Explorar el Código

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

Add identifiers to cio calls to avoid profile splits

GitOrigin-RevId: fec8cad4e87f8df910d729bd00acbf26d0931102
roo hutton hace 4 meses
padre
commit
24b16c1304

+ 3 - 2
services/web/app/src/Features/Subscription/FeaturesUpdater.mjs

@@ -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')

+ 4 - 3
services/web/app/views/_customer_io.pug

@@ -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 } : {});
+			}
 		}}();

+ 21 - 0
services/web/test/unit/src/Subscription/FeaturesUpdater.test.mjs

@@ -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',
           }
         )
       })