eventTracking.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /* eslint-disable
  2. camelcase,
  3. max-len,
  4. no-undef,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  12. */
  13. // For sending event data to metabase and google analytics
  14. // ---
  15. // by default,
  16. // event not sent to MB.
  17. // for MB, add event-tracking-mb='true'
  18. // by default, event sent to MB via sendMB
  19. // event not sent to GA.
  20. // for GA, add event-tracking-ga attribute, where the value is the GA category
  21. // Either GA or MB can use the attribute event-tracking-send-once='true' to
  22. // send event just once
  23. // MB will use the key and GA will use the action to determine if the event
  24. // has been sent
  25. // event-tracking-trigger attribute is required to send event
  26. const isInViewport = function(element) {
  27. const elTop = element.offset().top
  28. const elBtm = elTop + element.outerHeight()
  29. const viewportTop = $(window).scrollTop()
  30. const viewportBtm = viewportTop + $(window).height()
  31. return elBtm > viewportTop && elTop < viewportBtm
  32. }
  33. define(['base'], App =>
  34. App.directive('eventTracking', eventTracking => ({
  35. scope: {
  36. eventTracking: '@',
  37. eventSegmentation: '=?'
  38. },
  39. link(scope, element, attrs) {
  40. const sendGA = attrs.eventTrackingGa || false
  41. const sendMB = attrs.eventTrackingMb || false
  42. const sendMBFunction = attrs.eventTrackingSendOnce
  43. ? 'sendMBOnce'
  44. : 'sendMB'
  45. const sendGAFunction = attrs.eventTrackingSendOnce ? 'sendGAOnce' : 'send'
  46. const segmentation = scope.eventSegmentation || {}
  47. segmentation.page = window.location.pathname
  48. const sendEvent = function(scrollEvent) {
  49. /*
  50. @param {boolean} scrollEvent Use to unbind scroll event
  51. */
  52. if (sendMB) {
  53. eventTracking[sendMBFunction](scope.eventTracking, segmentation)
  54. }
  55. if (sendGA) {
  56. eventTracking[sendGAFunction](
  57. attrs.eventTrackingGa,
  58. attrs.eventTrackingAction || scope.eventTracking,
  59. attrs.eventTrackingLabel || ''
  60. )
  61. }
  62. if (scrollEvent) {
  63. return $(window).unbind('resize scroll')
  64. }
  65. }
  66. if (attrs.eventTrackingTrigger === 'load') {
  67. return sendEvent()
  68. } else if (attrs.eventTrackingTrigger === 'click') {
  69. return element.on('click', e => sendEvent())
  70. } else if (attrs.eventTrackingTrigger === 'hover') {
  71. let timer = null
  72. let timeoutAmt = 500
  73. if (attrs.eventHoverAmt) {
  74. timeoutAmt = parseInt(attrs.eventHoverAmt, 10)
  75. }
  76. return element
  77. .on('mouseenter', function() {
  78. timer = setTimeout(() => sendEvent(), timeoutAmt)
  79. })
  80. .on('mouseleave', () => clearTimeout(timer))
  81. } else if (
  82. attrs.eventTrackingTrigger === 'scroll' &&
  83. !eventTracking.eventInCache(scope.eventTracking)
  84. ) {
  85. $(window).on(
  86. 'resize scroll',
  87. _.throttle(() => {
  88. if (isInViewport(element)) {
  89. sendEvent(true)
  90. }
  91. }, 500)
  92. )
  93. }
  94. }
  95. })))