Просмотр исходного кода

Update B2B Groups and Enterprise banners (#11989)

* Tear down B2B banner ad split test and implement updated ads

GitOrigin-RevId: 7d09d54bef7cb4e2b2b597d3834e0f58551b179e
Thomas 3 лет назад
Родитель
Сommit
16b2d27fde

+ 5 - 25
services/web/app/src/Features/Project/ProjectController.js

@@ -532,26 +532,6 @@ const ProjectController = {
             }
             }
           )
           )
         },
         },
-        groupsAndEnterpriseBannerAssignment(cb) {
-          SplitTestHandler.getAssignment(
-            req,
-            res,
-            'groups-and-enterprise-banner',
-            (err, assignment) => {
-              if (err) {
-                logger.warn(
-                  { err },
-                  'failed to get "groups-and-enterprise-banner" split test assignment'
-                )
-
-                const defaultAssignment = { variant: 'default' }
-                cb(null, defaultAssignment)
-              } else {
-                cb(null, assignment)
-              }
-            }
-          )
-        },
         survey(cb) {
         survey(cb) {
           SurveyHandler.getSurvey(userId, (err, survey) => {
           SurveyHandler.getSurvey(userId, (err, survey) => {
             if (err) {
             if (err) {
@@ -573,7 +553,6 @@ const ProjectController = {
           notifications,
           notifications,
           user,
           user,
           userEmailsData,
           userEmailsData,
-          groupsAndEnterpriseBannerAssignment,
           userIsMemberOfGroupSubscription,
           userIsMemberOfGroupSubscription,
         } = results
         } = results
 
 
@@ -707,13 +686,15 @@ const ProjectController = {
           affiliation => affiliation.licence && affiliation.licence !== 'free'
           affiliation => affiliation.licence && affiliation.licence !== 'free'
         )
         )
 
 
-        // groupsAndEnterpriseBannerAssignment.variant = 'default' | 'empower' | 'save' | 'did-you-know'
         const showGroupsAndEnterpriseBanner =
         const showGroupsAndEnterpriseBanner =
-          groupsAndEnterpriseBannerAssignment.variant !== 'default' &&
           Features.hasFeature('saas') &&
           Features.hasFeature('saas') &&
           !userIsMemberOfGroupSubscription &&
           !userIsMemberOfGroupSubscription &&
           !hasPaidAffiliation
           !hasPaidAffiliation
 
 
+        const groupsAndEnterpriseBannerVariant =
+          showGroupsAndEnterpriseBanner &&
+          _.sample(['did-you-know', 'on-premise', 'people', 'FOMO'])
+
         ProjectController._injectProjectUsers(projects, (error, projects) => {
         ProjectController._injectProjectUsers(projects, (error, projects) => {
           if (error != null) {
           if (error != null) {
             return next(error)
             return next(error)
@@ -739,8 +720,7 @@ const ProjectController = {
             usersBestSubscription: results.usersBestSubscription,
             usersBestSubscription: results.usersBestSubscription,
             survey: results.survey,
             survey: results.survey,
             showGroupsAndEnterpriseBanner,
             showGroupsAndEnterpriseBanner,
-            groupsAndEnterpriseBannerVariant:
-              groupsAndEnterpriseBannerAssignment.variant,
+            groupsAndEnterpriseBannerVariant,
           }
           }
 
 
           const paidUser =
           const paidUser =

+ 6 - 23
services/web/app/src/Features/Project/ProjectListController.js

@@ -17,7 +17,6 @@ const NotificationsHandler = require('../Notifications/NotificationsHandler')
 const Modules = require('../../infrastructure/Modules')
 const Modules = require('../../infrastructure/Modules')
 const { OError, V1ConnectionError } = require('../Errors/Errors')
 const { OError, V1ConnectionError } = require('../Errors/Errors')
 const { User } = require('../../models/User')
 const { User } = require('../../models/User')
-const SplitTestHandler = require('../SplitTests/SplitTestHandler')
 const UserPrimaryEmailCheckHandler = require('../User/UserPrimaryEmailCheckHandler')
 const UserPrimaryEmailCheckHandler = require('../User/UserPrimaryEmailCheckHandler')
 const UserController = require('../User/UserController')
 const UserController = require('../User/UserController')
 const LimitationsManager = require('../Subscription/LimitationsManager')
 const LimitationsManager = require('../Subscription/LimitationsManager')
@@ -270,25 +269,7 @@ async function projectListReactPage(req, res, next) {
     status: prefetchedProjectsBlob ? 'success' : 'too-slow',
     status: prefetchedProjectsBlob ? 'success' : 'too-slow',
   })
   })
 
 
-  let showGroupsAndEnterpriseBanner = false
-  let groupsAndEnterpriseBannerAssignment
-
-  try {
-    groupsAndEnterpriseBannerAssignment =
-      await SplitTestHandler.promises.getAssignment(
-        req,
-        res,
-        'groups-and-enterprise-banner'
-      )
-  } catch (error) {
-    logger.error(
-      { err: error },
-      'failed to get "groups-and-enterprise-banner" split test assignment'
-    )
-  }
-
   let userIsMemberOfGroupSubscription = false
   let userIsMemberOfGroupSubscription = false
-
   try {
   try {
     const userIsMemberOfGroupSubscriptionPromise =
     const userIsMemberOfGroupSubscriptionPromise =
       await LimitationsManager.promises.userIsMemberOfGroupSubscription(user)
       await LimitationsManager.promises.userIsMemberOfGroupSubscription(user)
@@ -306,12 +287,15 @@ async function projectListReactPage(req, res, next) {
     affiliation => affiliation.licence && affiliation.licence !== 'free'
     affiliation => affiliation.licence && affiliation.licence !== 'free'
   )
   )
 
 
-  showGroupsAndEnterpriseBanner =
-    (groupsAndEnterpriseBannerAssignment?.variant ?? 'default') !== 'default' &&
+  const showGroupsAndEnterpriseBanner =
     Features.hasFeature('saas') &&
     Features.hasFeature('saas') &&
     !userIsMemberOfGroupSubscription &&
     !userIsMemberOfGroupSubscription &&
     !hasPaidAffiliation
     !hasPaidAffiliation
 
 
+  const groupsAndEnterpriseBannerVariant =
+    showGroupsAndEnterpriseBanner &&
+    _.sample(['did-you-know', 'on-premise', 'people', 'FOMO'])
+
   res.render('project/list-react', {
   res.render('project/list-react', {
     title: 'your_projects',
     title: 'your_projects',
     usersBestSubscription,
     usersBestSubscription,
@@ -327,8 +311,7 @@ async function projectListReactPage(req, res, next) {
     portalTemplates,
     portalTemplates,
     prefetchedProjectsBlob,
     prefetchedProjectsBlob,
     showGroupsAndEnterpriseBanner,
     showGroupsAndEnterpriseBanner,
-    groupsAndEnterpriseBannerVariant:
-      groupsAndEnterpriseBannerAssignment?.variant ?? 'default',
+    groupsAndEnterpriseBannerVariant,
     projectDashboardReact: true, // used in navbar
     projectDashboardReact: true, // used in navbar
   })
   })
 }
 }

+ 4 - 3
services/web/app/views/project/list/notifications.pug

@@ -267,12 +267,13 @@ include ../../_mixins/reconfirm_affiliation
 			)
 			)
 				.alert.alert-info
 				.alert.alert-info
 					.notification-body(ng-switch="groupsAndEnterpriseBannerVariant")
 					.notification-body(ng-switch="groupsAndEnterpriseBannerVariant")
-						span(ng-switch-when="empower") #{translate("empower_your_organization_to_work_in_overleaf")}
-						span(ng-switch-when="save") !{translate("save_money_groups_companies_research_organizations_can_save_money", {}, ['strong'])}
 						span(ng-switch-when="did-you-know") #{translate("did_you_know_that_overleaf_offers")}
 						span(ng-switch-when="did-you-know") #{translate("did_you_know_that_overleaf_offers")}
+						span(ng-switch-when="on-premise") Overleaf On-Premises: Does your company want to keep its data within its firewall? Overleaf offers Server Pro, an on-premises solution for companies. Get in touch to learn more.
+						span(ng-switch-when="people") Other people at your company may already be using Overleaf. Save money with Overleaf group and company-wide subscriptions. Request more information.
+						span(ng-switch-when="FOMO") Why do Fortune 500 companies and top research institutions trust Overleaf to streamline their collaboration? Get in touch to learn more.
 					.notification-action
 					.notification-action
 						a.pull-right.btn.btn-sm.btn-info(
 						a.pull-right.btn.btn-sm.btn-info(
-							href="/for/contact-sales"
+							href="/for/contact-sales{{urlVariantSuffix}}"
 							target="_blank"
 							target="_blank"
 							event-tracking="groups-and-enterprise-banner-click"
 							event-tracking="groups-and-enterprise-banner-click"
 							event-tracking-mb="true"
 							event-tracking-mb="true"

+ 0 - 2
services/web/frontend/extracted-translations.json

@@ -227,7 +227,6 @@
   "email_or_password_wrong_try_again": "",
   "email_or_password_wrong_try_again": "",
   "emails_and_affiliations_explanation": "",
   "emails_and_affiliations_explanation": "",
   "emails_and_affiliations_title": "",
   "emails_and_affiliations_title": "",
-  "empower_your_organization_to_work_in_overleaf": "",
   "end_of_document": "",
   "end_of_document": "",
   "error": "",
   "error": "",
   "error_performing_request": "",
   "error_performing_request": "",
@@ -670,7 +669,6 @@
   "revoke_invite": "",
   "revoke_invite": "",
   "rich_text_is_only_available_for_tex_files": "",
   "rich_text_is_only_available_for_tex_files": "",
   "role": "",
   "role": "",
-  "save_money_groups_companies_research_organizations_can_save_money": "",
   "save_or_cancel-cancel": "",
   "save_or_cancel-cancel": "",
   "save_or_cancel-or": "",
   "save_or_cancel-or": "",
   "save_or_cancel-save": "",
   "save_or_cancel-save": "",

+ 61 - 67
services/web/frontend/js/features/project-list/components/notifications/groups-and-enterprise-banner.tsx

@@ -1,4 +1,4 @@
-import { useCallback, useEffect, useMemo } from 'react'
+import { useCallback, useEffect } from 'react'
 import Notification from './notification'
 import Notification from './notification'
 import * as eventTracking from '../../../../infrastructure/event-tracking'
 import * as eventTracking from '../../../../infrastructure/event-tracking'
 import getMeta from '../../../../utils/meta'
 import getMeta from '../../../../utils/meta'
@@ -6,74 +6,58 @@ import customLocalStorage from '../../../../infrastructure/local-storage'
 import { useProjectListContext } from '../../context/project-list-context'
 import { useProjectListContext } from '../../context/project-list-context'
 import { Trans, useTranslation } from 'react-i18next'
 import { Trans, useTranslation } from 'react-i18next'
 
 
-type GroupsAndEnterpriseBannerVariant =
-  | 'default'
-  | 'empower'
-  | 'save'
-  | 'did-you-know'
+const variants = ['did-you-know', 'on-premise', 'people', 'FOMO'] as const
+type GroupsAndEnterpriseBannerVariant = typeof variants[number]
+
+let viewEventSent = false
 
 
 export default function GroupsAndEnterpriseBanner() {
 export default function GroupsAndEnterpriseBanner() {
   const { t } = useTranslation()
   const { t } = useTranslation()
   const { totalProjectsCount } = useProjectListContext()
   const { totalProjectsCount } = useProjectListContext()
-  const showGroupsAndEnterpriseBanner = getMeta(
-    'ol-showGroupsAndEnterpriseBanner'
-  ) as boolean
-  const groupsAndEnterpriseBannerVariant = getMeta(
-    'ol-groupsAndEnterpriseBannerVariant'
-  ) as GroupsAndEnterpriseBannerVariant
 
 
-  const eventTrackingSegmentation = useMemo(
-    () => ({
-      location: 'dashboard-banner-react',
-      variant: groupsAndEnterpriseBannerVariant,
-      page: '/project',
-    }),
-    [groupsAndEnterpriseBannerVariant]
+  const showGroupsAndEnterpriseBanner: boolean = getMeta(
+    'ol-showGroupsAndEnterpriseBanner'
   )
   )
+  const groupsAndEnterpriseBannerVariant: GroupsAndEnterpriseBannerVariant =
+    getMeta('ol-groupsAndEnterpriseBannerVariant')
 
 
-  const hasDismissedGroupsAndEnterpriseBanner = customLocalStorage.getItem(
-    'has_dismissed_groups_and_enterprise_banner'
-  )
+  const hasDismissedGroupsAndEnterpriseBanner = hasRecentlyDismissedBanner()
+
+  const contactSalesUrl = `/for/contact-sales-${
+    variants.indexOf(groupsAndEnterpriseBannerVariant) + 1
+  }`
+
+  const shouldRenderBanner =
+    showGroupsAndEnterpriseBanner &&
+    totalProjectsCount !== 0 &&
+    !hasDismissedGroupsAndEnterpriseBanner &&
+    isVariantValid(groupsAndEnterpriseBannerVariant)
 
 
   const handleClose = useCallback(() => {
   const handleClose = useCallback(() => {
     customLocalStorage.setItem(
     customLocalStorage.setItem(
       'has_dismissed_groups_and_enterprise_banner',
       'has_dismissed_groups_and_enterprise_banner',
-      true
+      new Date()
     )
     )
   }, [])
   }, [])
 
 
   const handleClickContact = useCallback(() => {
   const handleClickContact = useCallback(() => {
-    eventTracking.sendMB(
-      'groups-and-enterprise-banner-click',
-      eventTrackingSegmentation
-    )
-  }, [eventTrackingSegmentation])
+    eventTracking.sendMB('groups-and-enterprise-banner-click', {
+      location: 'dashboard-banner-react',
+      variant: groupsAndEnterpriseBannerVariant,
+    })
+  }, [groupsAndEnterpriseBannerVariant])
 
 
   useEffect(() => {
   useEffect(() => {
-    eventTracking.sendMB(
-      'groups-and-enterprise-banner-prompt',
-      eventTrackingSegmentation
-    )
-  }, [eventTrackingSegmentation])
-
-  if (
-    totalProjectsCount === 0 ||
-    hasDismissedGroupsAndEnterpriseBanner ||
-    !showGroupsAndEnterpriseBanner
-  ) {
-    return null
-  }
+    if (!viewEventSent && shouldRenderBanner) {
+      eventTracking.sendMB('groups-and-enterprise-banner-prompt', {
+        location: 'dashboard-banner-react',
+        variant: groupsAndEnterpriseBannerVariant,
+      })
+      viewEventSent = true
+    }
+  }, [shouldRenderBanner, groupsAndEnterpriseBannerVariant])
 
 
-  // `getText` function has no default switch case since the whole notification
-  // should not be rendered if the `groupsAndEnterpriseBannerVariant` is not valid
-  if (!isVariantValid(groupsAndEnterpriseBannerVariant)) {
-    return null
-  }
-
-  // this shouldn't ever happens since the value of `showGroupsAndEnterpriseBanner` should be false
-  // if `groupsAndEnterpriseBannerVariant` is 'default'
-  // but just adding this check as an extra measure
-  if (groupsAndEnterpriseBannerVariant === 'default') {
+  if (!shouldRenderBanner) {
     return null
     return null
   }
   }
 
 
@@ -85,8 +69,9 @@ export default function GroupsAndEnterpriseBanner() {
       <Notification.Action>
       <Notification.Action>
         <a
         <a
           className="pull-right btn btn-info btn-sm"
           className="pull-right btn btn-info btn-sm"
-          href="/for/contact-sales"
+          href={contactSalesUrl}
           target="_blank"
           target="_blank"
+          rel="noreferrer"
           onClick={handleClickContact}
           onClick={handleClickContact}
         >
         >
           {t('contact_sales')}
           {t('contact_sales')}
@@ -97,26 +82,35 @@ export default function GroupsAndEnterpriseBanner() {
 }
 }
 
 
 function isVariantValid(variant: GroupsAndEnterpriseBannerVariant) {
 function isVariantValid(variant: GroupsAndEnterpriseBannerVariant) {
-  return (
-    variant === 'empower' || variant === 'save' || variant === 'did-you-know'
-  )
+  return variants.includes(variant)
 }
 }
 
 
 function getText(variant: GroupsAndEnterpriseBannerVariant) {
 function getText(variant: GroupsAndEnterpriseBannerVariant) {
   switch (variant) {
   switch (variant) {
-    case 'empower':
-      return <Trans i18nKey="empower_your_organization_to_work_in_overleaf" />
-    case 'save':
-      return (
-        <Trans
-          i18nKey="save_money_groups_companies_research_organizations_can_save_money"
-          components={
-            /* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */
-            [<strong />]
-          }
-        />
-      )
     case 'did-you-know':
     case 'did-you-know':
       return <Trans i18nKey="did_you_know_that_overleaf_offers" />
       return <Trans i18nKey="did_you_know_that_overleaf_offers" />
+    case 'on-premise':
+      return 'Overleaf On-Premises: Does your company want to keep its data within its firewall? Overleaf offers Server Pro, an on-premises solution for companies. Get in touch to learn more.'
+    case 'people':
+      return 'Other people at your company may already be using Overleaf. Save money with Overleaf group and company-wide subscriptions. Request more information.'
+    case 'FOMO':
+      return 'Why do Fortune 500 companies and top research institutions trust Overleaf to streamline their collaboration? Get in touch to learn more.'
   }
   }
 }
 }
+
+function hasRecentlyDismissedBanner() {
+  const dismissed = customLocalStorage.getItem(
+    'has_dismissed_groups_and_enterprise_banner'
+  )
+  // previous banner set this to 'true', which shouldn't hide the new banner
+  if (!dismissed || dismissed === 'true') {
+    return false
+  }
+
+  const dismissedDate = new Date(dismissed)
+  const recentlyDismissedCutoff = new Date()
+  recentlyDismissedCutoff.setDate(recentlyDismissedCutoff.getDate() - 30) // 30 days
+
+  // once the dismissedDate passes the cut off mark, banner will be shown again
+  return dismissedDate > recentlyDismissedCutoff
+}

+ 9 - 4
services/web/frontend/js/main/project-list/notifications-controller.js

@@ -40,10 +40,15 @@ App.controller(
       'ol-groupsAndEnterpriseBannerVariant'
       'ol-groupsAndEnterpriseBannerVariant'
     )
     )
 
 
-    $scope.isVariantValid =
-      $scope.groupsAndEnterpriseBannerVariant === 'save' ||
-      $scope.groupsAndEnterpriseBannerVariant === 'empower' ||
-      $scope.groupsAndEnterpriseBannerVariant === 'did-you-know'
+    const valid = ['did-you-know', 'on-premise', 'people', 'FOMO']
+
+    $scope.isVariantValid = valid.includes(
+      $scope.groupsAndEnterpriseBannerVariant
+    )
+
+    $scope.urlVariantSuffix = $scope.isVariantValid
+      ? `-${valid.indexOf($scope.groupsAndEnterpriseBannerVariant) + 1}`
+      : ''
   }
   }
 )
 )
 
 

+ 0 - 2
services/web/locales/en.json

@@ -420,7 +420,6 @@
   "emails": "Emails",
   "emails": "Emails",
   "emails_and_affiliations_explanation": "Add additional email addresses to your account to access any upgrades your university or institution has, to make it easier for collaborators to find you, and to make sure you can recover your account.",
   "emails_and_affiliations_explanation": "Add additional email addresses to your account to access any upgrades your university or institution has, to make it easier for collaborators to find you, and to make sure you can recover your account.",
   "emails_and_affiliations_title": "Emails and Affiliations",
   "emails_and_affiliations_title": "Emails and Affiliations",
-  "empower_your_organization_to_work_in_overleaf": "Empower your organization to work in __appName__! Get a group or organizational plan.",
   "empty_zip_file": "Zip doesn’t contain any file",
   "empty_zip_file": "Zip doesn’t contain any file",
   "en": "English",
   "en": "English",
   "end_of_document": "End of document",
   "end_of_document": "End of document",
@@ -1273,7 +1272,6 @@
   "saml": "SAML",
   "saml": "SAML",
   "saml_create_admin_instructions": "Choose an email address for the first __appName__ admin account. This should correspond to an account in the SAML system. You will then be asked to log in with this account.",
   "saml_create_admin_instructions": "Choose an email address for the first __appName__ admin account. This should correspond to an account in the SAML system. You will then be asked to log in with this account.",
   "save_20_percent_by_paying_annually": "Save 20% by paying annually",
   "save_20_percent_by_paying_annually": "Save 20% by paying annually",
-  "save_money_groups_companies_research_organizations_can_save_money": "<0>Save Money</0>! Groups, Companies and Research Organizations can save money with our Group and Enterprise plans — request information or a quote.",
   "save_or_cancel-cancel": "Cancel",
   "save_or_cancel-cancel": "Cancel",
   "save_or_cancel-or": "or",
   "save_or_cancel-or": "or",
   "save_or_cancel-save": "Save",
   "save_or_cancel-save": "Save",

+ 68 - 14
services/web/test/frontend/features/project-list/components/notifications.test.tsx

@@ -658,6 +658,11 @@ describe('<UserNotifications />', function () {
           totalSize: projects.length,
           totalSize: projects.length,
         },
         },
       })
       })
+
+      window.metaAttributesCache.set(
+        'ol-groupsAndEnterpriseBannerVariant',
+        'did-you-know'
+      )
     })
     })
 
 
     afterEach(function () {
     afterEach(function () {
@@ -665,7 +670,7 @@ describe('<UserNotifications />', function () {
       window.metaAttributesCache = window.metaAttributesCache || new Map()
       window.metaAttributesCache = window.metaAttributesCache || new Map()
     })
     })
 
 
-    it('does not show the banner for users that are in group or are affiliated or assigned in the `default` variant', async function () {
+    it('does not show the banner for users that are in group or are affiliated', async function () {
       window.metaAttributesCache.set('ol-showGroupsAndEnterpriseBanner', false)
       window.metaAttributesCache.set('ol-showGroupsAndEnterpriseBanner', false)
 
 
       renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
       renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
@@ -674,13 +679,45 @@ describe('<UserNotifications />', function () {
       expect(screen.queryByRole('link', { name: 'Contact Sales' })).to.be.null
       expect(screen.queryByRole('link', { name: 'Contact Sales' })).to.be.null
     })
     })
 
 
-    it('does not show the banner for users that have already dismissed it', async function () {
+    it('shows the banner for users that have dismissed the previous banners', async function () {
       window.metaAttributesCache.set('ol-showGroupsAndEnterpriseBanner', true)
       window.metaAttributesCache.set('ol-showGroupsAndEnterpriseBanner', true)
       localStorage.setItem('has_dismissed_groups_and_enterprise_banner', true)
       localStorage.setItem('has_dismissed_groups_and_enterprise_banner', true)
 
 
       renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
       renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
       await fetchMock.flush(true)
       await fetchMock.flush(true)
 
 
+      expect(screen.queryByRole('link', { name: 'Contact Sales' })).to.not.be
+        .null
+    })
+
+    it('shows the banner for users that have dismissed the banner more than 30 days ago', async function () {
+      const dismissed = new Date()
+      dismissed.setDate(dismissed.getDate() - 31) // 31 days
+      window.metaAttributesCache.set('ol-showGroupsAndEnterpriseBanner', true)
+      localStorage.setItem(
+        'has_dismissed_groups_and_enterprise_banner',
+        dismissed
+      )
+
+      renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
+      await fetchMock.flush(true)
+
+      expect(screen.queryByRole('link', { name: 'Contact Sales' })).to.not.be
+        .null
+    })
+
+    it('does not show the banner for users that have dismissed the banner within the last 30 days', async function () {
+      const dismissed = new Date()
+      dismissed.setDate(dismissed.getDate() - 29) // 29 days
+      window.metaAttributesCache.set('ol-showGroupsAndEnterpriseBanner', true)
+      localStorage.setItem(
+        'has_dismissed_groups_and_enterprise_banner',
+        dismissed
+      )
+
+      renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
+      await fetchMock.flush(true)
+
       expect(screen.queryByRole('link', { name: 'Contact Sales' })).to.be.null
       expect(screen.queryByRole('link', { name: 'Contact Sales' })).to.be.null
     })
     })
 
 
@@ -711,55 +748,72 @@ describe('<UserNotifications />', function () {
         localStorage.clear()
         localStorage.clear()
       })
       })
 
 
-      it('will show the correct text for the `save` split test variant', async function () {
+      it('will show the correct text for the `did-you-know` variant', async function () {
         window.metaAttributesCache.set(
         window.metaAttributesCache.set(
           'ol-groupsAndEnterpriseBannerVariant',
           'ol-groupsAndEnterpriseBannerVariant',
-          'save'
+          'did-you-know'
         )
         )
 
 
         renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
         renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
         await fetchMock.flush(true)
         await fetchMock.flush(true)
 
 
         screen.getByText(
         screen.getByText(
-          /Groups, Companies and Research Organizations can save money with our Group and Enterprise plans — request information or a quote./
+          'Did you know that Overleaf offers group and organization-wide subscription options? Request information or a quote.'
         )
         )
         const link = screen.getByRole('link', { name: 'Contact Sales' })
         const link = screen.getByRole('link', { name: 'Contact Sales' })
 
 
-        expect(link.getAttribute('href')).to.equal(`/for/contact-sales`)
+        expect(link.getAttribute('href')).to.equal(`/for/contact-sales-1`)
       })
       })
 
 
-      it('will show the correct text for the `did-you-know` split test variant', async function () {
+      it('will show the correct text for the `on-premise` variant', async function () {
         window.metaAttributesCache.set(
         window.metaAttributesCache.set(
           'ol-groupsAndEnterpriseBannerVariant',
           'ol-groupsAndEnterpriseBannerVariant',
-          'did-you-know'
+          'on-premise'
         )
         )
 
 
         renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
         renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
         await fetchMock.flush(true)
         await fetchMock.flush(true)
 
 
         screen.getByText(
         screen.getByText(
-          'Did you know that Overleaf offers group and organization-wide subscription options? Request information or a quote.'
+          'Overleaf On-Premises: Does your company want to keep its data within its firewall? Overleaf offers Server Pro, an on-premises solution for companies. Get in touch to learn more.'
+        )
+        const link = screen.getByRole('link', { name: 'Contact Sales' })
+
+        expect(link.getAttribute('href')).to.equal(`/for/contact-sales-2`)
+      })
+
+      it('will show the correct text for the `people` variant', async function () {
+        window.metaAttributesCache.set(
+          'ol-groupsAndEnterpriseBannerVariant',
+          'people'
+        )
+
+        renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
+        await fetchMock.flush(true)
+
+        screen.getByText(
+          'Other people at your company may already be using Overleaf. Save money with Overleaf group and company-wide subscriptions. Request more information.'
         )
         )
         const link = screen.getByRole('link', { name: 'Contact Sales' })
         const link = screen.getByRole('link', { name: 'Contact Sales' })
 
 
-        expect(link.getAttribute('href')).to.equal(`/for/contact-sales`)
+        expect(link.getAttribute('href')).to.equal(`/for/contact-sales-3`)
       })
       })
 
 
-      it('will show the correct text for the `empower` split test variant', async function () {
+      it('will show the correct text for the `FOMO` variant', async function () {
         window.metaAttributesCache.set(
         window.metaAttributesCache.set(
           'ol-groupsAndEnterpriseBannerVariant',
           'ol-groupsAndEnterpriseBannerVariant',
-          'empower'
+          'FOMO'
         )
         )
 
 
         renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
         renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
         await fetchMock.flush(true)
         await fetchMock.flush(true)
 
 
         screen.getByText(
         screen.getByText(
-          'Empower your organization to work in Overleaf! Get a group or organizational plan.'
+          'Why do Fortune 500 companies and top research institutions trust Overleaf to streamline their collaboration? Get in touch to learn more.'
         )
         )
         const link = screen.getByRole('link', { name: 'Contact Sales' })
         const link = screen.getByRole('link', { name: 'Contact Sales' })
 
 
-        expect(link.getAttribute('href')).to.equal(`/for/contact-sales`)
+        expect(link.getAttribute('href')).to.equal(`/for/contact-sales-4`)
       })
       })
     })
     })
   })
   })