diff --git a/services/web/app/src/Features/Project/ProjectListController.mjs b/services/web/app/src/Features/Project/ProjectListController.mjs index 1119e14cc1..9f174f31af 100644 --- a/services/web/app/src/Features/Project/ProjectListController.mjs +++ b/services/web/app/src/Features/Project/ProjectListController.mjs @@ -179,7 +179,7 @@ async function projectListPage(req, res, next) { userId, `email isAdmin emails features alphaProgram betaProgram lastPrimaryEmailCheck lastActive signUpDate ace refProviders${ isSaas - ? ' enrollment writefull completedTutorials aiFeatures aiErrorAssistant' + ? ' enrollment writefull completedTutorials aiFeatures aiErrorAssistant labsProgram' : '' }` ) diff --git a/services/web/app/src/infrastructure/ExpressLocals.mjs b/services/web/app/src/infrastructure/ExpressLocals.mjs index 09e8f072aa..c20a883fc4 100644 --- a/services/web/app/src/infrastructure/ExpressLocals.mjs +++ b/services/web/app/src/infrastructure/ExpressLocals.mjs @@ -418,6 +418,8 @@ export default async function (webRouter, privateApiRouter, publicApiRouter) { cioSiteId: Settings.analytics?.cio?.siteId, linkedInInsightsPartnerId: Settings.analytics?.linkedIn?.partnerId, enablePandocConversions: Settings.enablePandocConversions, + mixpanelLabsToken: + Settings.labs?.enable && Settings.analytics?.mixpanel?.labsToken, } next() }) diff --git a/services/web/app/views/project/_mixpanel_autocapture.pug b/services/web/app/views/project/_mixpanel_autocapture.pug new file mode 100644 index 0000000000..184483ff60 --- /dev/null +++ b/services/web/app/views/project/_mixpanel_autocapture.pug @@ -0,0 +1,77 @@ +if user && user.labsProgram && ExposedSettings.mixpanelLabsToken + script( + type='text/javascript' + nonce=scriptNonce + id='mp-loader' + data-mixpanel-token=ExposedSettings.mixpanelLabsToken + ). + ;(function (f, b) { + if (!b.__SV) { + var e, g, i, h + window.mixpanel = b + b._i = [] + b.init = function (e, f, c) { + function g(a, d) { + var b = d.split('.') + 2 == b.length && ((a = a[b[0]]), (d = b[1])) + a[d] = function () { + a.push([d].concat(Array.prototype.slice.call(arguments, 0))) + } + } + + var a = b + 'undefined' !== typeof c ? (a = b[c] = []) : (c = 'mixpanel') + a.people = a.people || [] + a.toString = function (a) { + var d = 'mixpanel' + 'mixpanel' !== c && (d += '.' + c) + a || (d += ' (stub)') + return d + } + a.people.toString = function () { + return a.toString(1) + '.people (stub)' + } + i = 'disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking start_batch_senders people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove'.split(' ') + for (h = 0; h < i.length; h++) g(a, i[h]) + var j = 'set set_once union unset remove delete'.split(' ') + a.get_group = function () { + function b(c) { + d[c] = function () { + call2_args = arguments + call2 = [c].concat(Array.prototype.slice.call(call2_args, 0)) + a.push([e, call2]) + } + } + + for (var d = {}, e = ['get_group'].concat(Array.prototype.slice.call(arguments, 0)), c = 0; c < j.length; c++) b(j[c]) + return d + } + b._i.push([e, f, c]) + } + b.__SV = 1.2 + e = f.createElement('script') + e.type = 'text/javascript' + e.async = !0 + e.src = 'undefined' !== typeof MIXPANEL_CUSTOM_LIB_URL ? MIXPANEL_CUSTOM_LIB_URL : 'file:' === f.location.protocol && '//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js'.match(/^\/\//) ? 'https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js' : '//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js' + g = f.getElementsByTagName('script')[0] + g.parentNode.insertBefore(e, g) + } + })(document, window.mixpanel || []) + + var mixpanelSettings = document.querySelector('#mp-loader').dataset + var mixpanelToken = mixpanelSettings.mixpanelToken + if (mixpanelToken) { + mixpanel.init(mixpanelToken, { + api_host: 'https://api-eu.mixpanel.com', + autocapture: { + capture_text_content: false, + input: true, + rage_click: true, + dead_click: true, + scroll: true, + submit: true, + click: true, + pageview: 'full-url', + }, + }) + } diff --git a/services/web/app/views/project/ide-react-detached.pug b/services/web/app/views/project/ide-react-detached.pug index fa695b1af5..47325ad49f 100644 --- a/services/web/app/views/project/ide-react-detached.pug +++ b/services/web/app/views/project/ide-react-detached.pug @@ -13,5 +13,8 @@ block vars block content #pdf-preview-detached-root +block append head-scripts + include ./_mixpanel_autocapture.pug + block append meta include editor/_meta diff --git a/services/web/app/views/project/ide-react.pug b/services/web/app/views/project/ide-react.pug index ef93ae9e8d..21f0d4b7b4 100644 --- a/services/web/app/views/project/ide-react.pug +++ b/services/web/app/views/project/ide-react.pug @@ -32,3 +32,6 @@ block prepend foot-scripts src=(wsUrl || '/socket.io') + '/socket.io.js' defer=deferScripts ) + +block append head-scripts + include ./_mixpanel_autocapture.pug diff --git a/services/web/app/views/project/list-react.pug b/services/web/app/views/project/list-react.pug index 148420a33c..d3e9cf1ccc 100644 --- a/services/web/app/views/project/list-react.pug +++ b/services/web/app/views/project/list-react.pug @@ -95,3 +95,6 @@ block append meta block content #project-list-root + +block append head-scripts + include ./_mixpanel_autocapture.pug