plans.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import '../../../marketing'
  2. import '../../../features/plans/group-plan-modal'
  3. import * as eventTracking from '../../../infrastructure/event-tracking'
  4. import getMeta from '../../../utils/meta'
  5. let currentView = getMeta('ol-currentView')
  6. let currentCurrencyCode = getMeta('ol-recommendedCurrency')
  7. const plansPageLayoutV3Variant =
  8. getMeta('ol-splitTestVariants')?.['plans-page-layout-v3'] ?? 'default'
  9. if (window.location.href.includes('validate-pre-rendering=true')) {
  10. validatePreRendering()
  11. }
  12. function selectView(view) {
  13. document.querySelectorAll('[data-ol-view-tab]').forEach(el => {
  14. if (el.getAttribute('data-ol-view-tab') === view) {
  15. el.classList.add('active')
  16. } else {
  17. el.classList.remove('active')
  18. }
  19. })
  20. document.querySelectorAll('[data-ol-view]').forEach(el => {
  21. el.hidden = el.getAttribute('data-ol-view') !== view
  22. })
  23. updateAnnualSavingBanner(view)
  24. currentView = view
  25. updateLinkTargets()
  26. }
  27. function setUpViewSwitching(liEl) {
  28. liEl.querySelector('button').addEventListener('click', function (e) {
  29. e.preventDefault()
  30. const view = liEl.getAttribute('data-ol-view-tab')
  31. eventTracking.send('subscription-funnel', 'plans-page', `${view}-prices`)
  32. eventTracking.sendMB('plans-page-toggle', {
  33. button: view,
  34. 'plans-page-layout-v3': plansPageLayoutV3Variant,
  35. })
  36. selectView(view)
  37. })
  38. }
  39. function setUpCurrencySwitching(linkEl) {
  40. linkEl.addEventListener('click', function (e) {
  41. e.preventDefault()
  42. const currencyCode = linkEl.getAttribute('data-ol-currencyCode-switch')
  43. document.querySelectorAll('[data-ol-currencyCode]').forEach(el => {
  44. el.hidden = el.getAttribute('data-ol-currencyCode') !== currencyCode
  45. })
  46. currentCurrencyCode = currencyCode
  47. eventTracking.sendMB('plans-page-currency', { currency: currencyCode })
  48. updateLinkTargets()
  49. })
  50. }
  51. function setUpSubscriptionTracking(linkEl) {
  52. linkEl.addEventListener('click', function () {
  53. const plansPageLayoutV3Variant =
  54. getMeta('ol-splitTestVariants')?.['plans-page-layout-v3'] ?? 'default'
  55. const plan =
  56. linkEl.getAttribute('data-ol-tracking-plan') ||
  57. linkEl.getAttribute('data-ol-start-new-subscription')
  58. const location = linkEl.getAttribute('data-ol-location')
  59. const period = linkEl.getAttribute('data-ol-item-view') || currentView
  60. const DEFAULT_EVENT_TRACKING_KEY = 'plans-page-click'
  61. const eventTrackingKey =
  62. linkEl.getAttribute('data-ol-event-tracking-key') ||
  63. DEFAULT_EVENT_TRACKING_KEY
  64. const eventTrackingSegmentation = {
  65. button: plan,
  66. location,
  67. 'billing-period': period,
  68. }
  69. if (eventTrackingKey === DEFAULT_EVENT_TRACKING_KEY) {
  70. eventTrackingSegmentation['plans-page-layout-v3'] =
  71. plansPageLayoutV3Variant
  72. }
  73. const customLabel = linkEl.getAttribute('data-ol-tracking-label')
  74. const computedLabel = currentView === 'annual' ? `${plan}_annual` : plan
  75. const label = customLabel || computedLabel
  76. eventTracking.sendMB('plans-page-start-trial') // deprecated by plans-page-click
  77. eventTracking.send('subscription-funnel', 'sign_up_now_button', label) // deprecated by plans-page-click
  78. eventTracking.sendMB(eventTrackingKey, eventTrackingSegmentation)
  79. })
  80. }
  81. const searchParams = new URLSearchParams(window.location.search)
  82. export function updateLinkTargets() {
  83. document.querySelectorAll('[data-ol-start-new-subscription]').forEach(el => {
  84. if (el.hasAttribute('data-ol-has-custom-href')) return
  85. const plan = el.getAttribute('data-ol-start-new-subscription')
  86. const view = el.getAttribute('data-ol-item-view') || currentView
  87. const suffix = view === 'annual' ? `-annual` : `_free_trial_7_days`
  88. const planCode = `${plan}${suffix}`
  89. const location = el.getAttribute('data-ol-location')
  90. const itmCampaign = searchParams.get('itm_campaign') || 'plans'
  91. const itmContent =
  92. itmCampaign === 'plans' ? location : searchParams.get('itm_content')
  93. const queryString = new URLSearchParams({
  94. planCode,
  95. currency: currentCurrencyCode,
  96. itm_campaign: itmCampaign,
  97. })
  98. if (itmContent) {
  99. queryString.set('itm_content', itmContent)
  100. }
  101. if (searchParams.get('itm_referrer')) {
  102. queryString.set('itm_referrer', searchParams.get('itm_referrer'))
  103. }
  104. el.href = `/user/subscription/new?${queryString.toString()}`
  105. })
  106. }
  107. function updateAnnualSavingBanner(view) {
  108. const tooltipEl = document.querySelector('[data-ol-annual-saving-tooltip]')
  109. if (view === 'annual') {
  110. tooltipEl.classList.add('annual-selected')
  111. } else {
  112. tooltipEl.classList.remove('annual-selected')
  113. }
  114. }
  115. function selectViewFromHash() {
  116. try {
  117. const params = new URLSearchParams(window.location.hash.substring(1))
  118. const view = params.get('view')
  119. if (view) {
  120. // make sure the selected view is valid
  121. if (document.querySelector(`[data-ol-view-tab="${view}"]`)) {
  122. selectView(view)
  123. // clear the hash so it doesn't persist when switching plans
  124. window.location.hash = ''
  125. }
  126. }
  127. } catch {
  128. // do nothing
  129. }
  130. }
  131. function validatePreRendering() {
  132. document.querySelectorAll('[data-ol-view-tab]').forEach(el => {
  133. console.assert(
  134. (el.getAttribute('data-ol-view-tab') === currentView) ===
  135. el.classList.contains('active'),
  136. el
  137. )
  138. })
  139. document.querySelectorAll('[data-ol-view]').forEach(el => {
  140. console.assert(
  141. (el.hidden === el.getAttribute('data-ol-view')) !== currentView,
  142. el
  143. )
  144. })
  145. const plansPageLayoutV3Variant = getMeta('ol-splitTestVariants')?.[
  146. 'plans-page-layout-v3'
  147. ]
  148. if (plansPageLayoutV3Variant !== 'new-plans-page') {
  149. const tooltipEl = document.querySelector('[data-ol-annual-saving-tooltip]')
  150. console.assert(
  151. (currentView === 'annual') ===
  152. tooltipEl.classList.contains('annual-selected'),
  153. tooltipEl
  154. )
  155. }
  156. console.log('validated pre-rendering')
  157. }
  158. document.querySelectorAll('[data-ol-view-tab]').forEach(setUpViewSwitching)
  159. document
  160. .querySelectorAll('[data-ol-currencyCode-switch]')
  161. .forEach(setUpCurrencySwitching)
  162. document
  163. .querySelectorAll('[data-ol-start-new-subscription]')
  164. .forEach(setUpSubscriptionTracking)
  165. updateLinkTargets()
  166. selectViewFromHash()
  167. window.addEventListener('hashchange', selectViewFromHash)