mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Add cookie banner (#6627)
* Add cookie banner Co-authored-by: Alf Eaton <alf.eaton@overleaf.com> Co-authored-by: Miguel Serrano <mserranom@users.noreply.github.com> GitOrigin-RevId: a3625d4e6357ff58c7c47532901c382bedbe07e0
This commit is contained in:
parent
a5e09a6200
commit
76beba4393
10 changed files with 148 additions and 47 deletions
|
@ -277,16 +277,6 @@ module.exports = function (webRouter, privateApiRouter, publicApiRouter) {
|
||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
|
|
||||||
webRouter.use(function (req, res, next) {
|
|
||||||
res.locals.gaToken =
|
|
||||||
Settings.analytics && Settings.analytics.ga && Settings.analytics.ga.token
|
|
||||||
res.locals.gaTokenV4 =
|
|
||||||
Settings.analytics &&
|
|
||||||
Settings.analytics.ga &&
|
|
||||||
Settings.analytics.ga.tokenV4
|
|
||||||
next()
|
|
||||||
})
|
|
||||||
|
|
||||||
webRouter.use(function (req, res, next) {
|
webRouter.use(function (req, res, next) {
|
||||||
res.locals.getReqQueryParam = field =>
|
res.locals.getReqQueryParam = field =>
|
||||||
req.query != null ? req.query[field] : undefined
|
req.query != null ? req.query[field] : undefined
|
||||||
|
@ -387,6 +377,15 @@ module.exports = function (webRouter, privateApiRouter, publicApiRouter) {
|
||||||
sentryEnvironment: Settings.sentry.environment,
|
sentryEnvironment: Settings.sentry.environment,
|
||||||
sentryRelease: Settings.sentry.release,
|
sentryRelease: Settings.sentry.release,
|
||||||
enableSubscriptions: Settings.enableSubscriptions,
|
enableSubscriptions: Settings.enableSubscriptions,
|
||||||
|
gaToken:
|
||||||
|
Settings.analytics &&
|
||||||
|
Settings.analytics.ga &&
|
||||||
|
Settings.analytics.ga.token,
|
||||||
|
gaTokenV4:
|
||||||
|
Settings.analytics &&
|
||||||
|
Settings.analytics.ga &&
|
||||||
|
Settings.analytics.ga.tokenV4,
|
||||||
|
cookieDomain: Settings.cookieDomain,
|
||||||
}
|
}
|
||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
|
|
5
services/web/app/views/_cookie_banner.pug
Normal file
5
services/web/app/views/_cookie_banner.pug
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
.cookie-banner.hidden-print.hidden
|
||||||
|
.cookie-banner-content We only use cookies for essential purposes and to improve your experience on our site. You can find out more in our <a href="/legal#Cookies">cookie policy</a>.
|
||||||
|
.cookie-banner-actions
|
||||||
|
button(type="button" class="btn btn-link btn-sm" data-ol-cookie-banner-set-consent="essential") Essential cookies only
|
||||||
|
button(type="button" class="btn btn-info btn-sm" data-ol-cookie-banner-set-consent="all") Accept all cookies
|
50
services/web/app/views/_google_analytics.pug
Normal file
50
services/web/app/views/_google_analytics.pug
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
if (typeof(ExposedSettings.gaTokenV4) != "undefined" || typeof(ExposedSettings.gaToken) != "undefined")
|
||||||
|
script(type="text/javascript", nonce=scriptNonce, id="ga-loader" data-ga-token=ExposedSettings.gaToken data-ga-token-v4=ExposedSettings.gaTokenV4 data-cookie-domain=ExposedSettings.cookieDomain).
|
||||||
|
var gaSettings = document.querySelector('#ga-loader').dataset;
|
||||||
|
var gaid = gaSettings.gaTokenV4;
|
||||||
|
var gaToken = gaSettings.gaToken;
|
||||||
|
var cookieDomain = gaSettings.cookieDomain;
|
||||||
|
if(gaid) {
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag(){
|
||||||
|
dataLayer.push(arguments);
|
||||||
|
}
|
||||||
|
gtag('js', new Date());
|
||||||
|
gtag('config', gaid, { 'anonymize_ip': true });
|
||||||
|
}
|
||||||
|
if (gaToken) {
|
||||||
|
window.ga = window.ga || function () {
|
||||||
|
(window.ga.q = window.ga.q || []).push(arguments);
|
||||||
|
}, window.ga.l = 1 * new Date();
|
||||||
|
}
|
||||||
|
var loadGA = window.olLoadGA = function() {
|
||||||
|
if (gaid) {
|
||||||
|
var s = document.createElement('script');
|
||||||
|
s.setAttribute('async', 'async');
|
||||||
|
s.setAttribute('src', 'https://www.googletagmanager.com/gtag/js?id=' + gaid);
|
||||||
|
document.querySelector('head').append(s);
|
||||||
|
}
|
||||||
|
if (gaToken) {
|
||||||
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||||
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||||
|
ga('create', gaToken, cookieDomain.replace(/^\./, ""));
|
||||||
|
ga('set', 'anonymizeIp', true);
|
||||||
|
ga('send', 'pageview');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Check if consent given (features/cookie-banner)
|
||||||
|
var oaCookie = document.cookie.split('; ').find(function(cookie) {
|
||||||
|
return cookie.startsWith('oa=');
|
||||||
|
});
|
||||||
|
if(oaCookie) {
|
||||||
|
var oaCookieValue = oaCookie.split('=')[1];
|
||||||
|
if(oaCookieValue === '1') {
|
||||||
|
loadGA();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
script(type="text/javascript", nonce=scriptNonce).
|
||||||
|
window.ga = function() { console.log("would send to GA", arguments) };
|
||||||
|
window.gtag = function() { console.log("would send to GA4", arguments) };
|
|
@ -25,43 +25,7 @@ html(
|
||||||
link(rel="alternate", href=subdomainDetails.url+currentUrl, hreflang=subdomainDetails.lngCode)
|
link(rel="alternate", href=subdomainDetails.url+currentUrl, hreflang=subdomainDetails.lngCode)
|
||||||
|
|
||||||
//- Scripts
|
//- Scripts
|
||||||
|
include _google_analytics
|
||||||
//- Google Analytics
|
|
||||||
if (typeof(gaToken) != "undefined")
|
|
||||||
script(type="text/javascript", nonce=scriptNonce).
|
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
||||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
|
||||||
script(type="text/javascript", nonce=scriptNonce).
|
|
||||||
ga('create', '#{gaToken}', '#{settings.cookieDomain.replace(/^\./, "")}');
|
|
||||||
ga('set', 'anonymizeIp', true);
|
|
||||||
ga('send', 'pageview');
|
|
||||||
|
|
||||||
try {
|
|
||||||
ga.isBlocked = localStorage.getItem('gaBlocked') === 'true'
|
|
||||||
if (!ga.isBlocked) {
|
|
||||||
window.addEventListener('load', function () {
|
|
||||||
setTimeout(function () {
|
|
||||||
if (!ga.loaded) localStorage.setItem('gaBlocked', 'true')
|
|
||||||
}, 4000)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} catch (e) {}
|
|
||||||
else
|
|
||||||
script(type="text/javascript", nonce=scriptNonce).
|
|
||||||
window.ga = function() { console.log("would send to GA", arguments) };
|
|
||||||
|
|
||||||
if (typeof(gaTokenV4) != "undefined")
|
|
||||||
script(async, nonce=scriptNonce, src='https://www.googletagmanager.com/gtag/js?id=' + gaTokenV4)
|
|
||||||
script(type="text/javascript", nonce=scriptNonce).
|
|
||||||
window.dataLayer = window.dataLayer || [];
|
|
||||||
function gtag(){dataLayer.push(arguments);}
|
|
||||||
gtag('js', new Date());
|
|
||||||
gtag('config', '#{gaTokenV4}');
|
|
||||||
else
|
|
||||||
script(type = "text/javascript", nonce = scriptNonce).
|
|
||||||
window.gtag = function() { console.log("would send to GA4", arguments) };
|
|
||||||
|
|
||||||
block meta
|
block meta
|
||||||
meta(name="ol-csrfToken" content=csrfToken)
|
meta(name="ol-csrfToken" content=csrfToken)
|
||||||
|
|
|
@ -17,4 +17,6 @@ block body
|
||||||
else
|
else
|
||||||
include layout/fat-footer
|
include layout/fat-footer
|
||||||
|
|
||||||
|
include _cookie_banner
|
||||||
|
|
||||||
!= moduleIncludes("contactModal-marketing", locals)
|
!= moduleIncludes("contactModal-marketing", locals)
|
||||||
|
|
|
@ -15,4 +15,6 @@ block body
|
||||||
else
|
else
|
||||||
include layout/fat-footer
|
include layout/fat-footer
|
||||||
|
|
||||||
|
include _cookie_banner
|
||||||
|
|
||||||
!= moduleIncludes("contactModal", locals)
|
!= moduleIncludes("contactModal", locals)
|
||||||
|
|
43
services/web/frontend/js/features/cookie-banner/index.js
Normal file
43
services/web/frontend/js/features/cookie-banner/index.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
function loadGA() {
|
||||||
|
if (window.olLoadGA) {
|
||||||
|
window.olLoadGA()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setConsent(value) {
|
||||||
|
document.querySelector('.cookie-banner').classList.add('hidden')
|
||||||
|
const cookieDomain = window.ExposedSettings.cookieDomain
|
||||||
|
const oneYearInSeconds = 60 * 60 * 24 * 365
|
||||||
|
const cookieAttributes =
|
||||||
|
'; domain=' +
|
||||||
|
cookieDomain +
|
||||||
|
'; max-age=' +
|
||||||
|
oneYearInSeconds +
|
||||||
|
'; SameSite=Lax; Secure'
|
||||||
|
if (value === 'all') {
|
||||||
|
document.cookie = 'oa=1' + cookieAttributes
|
||||||
|
loadGA()
|
||||||
|
} else {
|
||||||
|
document.cookie = 'oa=0' + cookieAttributes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.ExposedSettings.gaToken || window.ExposedSettings.gaTokenV4) {
|
||||||
|
document
|
||||||
|
.querySelectorAll('[data-ol-cookie-banner-set-consent]')
|
||||||
|
.forEach(el => {
|
||||||
|
el.addEventListener('click', function (e) {
|
||||||
|
e.preventDefault()
|
||||||
|
const consentType = el.getAttribute('data-ol-cookie-banner-set-consent')
|
||||||
|
setConsent(consentType)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const oaCookie = document.cookie.split('; ').find(c => c.startsWith('oa='))
|
||||||
|
if (!oaCookie) {
|
||||||
|
const cookieBannerEl = document.querySelector('.cookie-banner')
|
||||||
|
if (cookieBannerEl) {
|
||||||
|
cookieBannerEl.classList.remove('hidden')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,6 +51,7 @@ import './services/queued-http'
|
||||||
import './services/validateCaptcha'
|
import './services/validateCaptcha'
|
||||||
import './services/validateCaptchaV3'
|
import './services/validateCaptchaV3'
|
||||||
import './filters/formatDate'
|
import './filters/formatDate'
|
||||||
|
import './features/cookie-banner'
|
||||||
import '../../modules/modules-main.js'
|
import '../../modules/modules-main.js'
|
||||||
import './cdn-load-test'
|
import './cdn-load-test'
|
||||||
angular.module('SharelatexApp').config(function ($locationProvider) {
|
angular.module('SharelatexApp').config(function ($locationProvider) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import './features/contact-form'
|
||||||
import './features/event-tracking'
|
import './features/event-tracking'
|
||||||
import './features/fallback-image'
|
import './features/fallback-image'
|
||||||
import './features/multi-submit'
|
import './features/multi-submit'
|
||||||
|
import './features/cookie-banner'
|
||||||
|
|
||||||
$('[data-ol-lang-selector-tooltip]').tooltip({ trigger: 'hover' })
|
$('[data-ol-lang-selector-tooltip]').tooltip({ trigger: 'hover' })
|
||||||
$('[data-toggle="tooltip"]').tooltip()
|
$('[data-toggle="tooltip"]').tooltip()
|
||||||
|
|
|
@ -262,3 +262,37 @@ footer.site-footer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cookie-banner {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
line-height: 1;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 100;
|
||||||
|
color: @text-color;
|
||||||
|
background: @ol-blue-gray-0;
|
||||||
|
box-shadow: 0 -2px 1px 0px #2c36455c;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: @footer-link-color;
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
color: @footer-link-hover-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cookie-banner-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cookie-banner-actions {
|
||||||
|
flex-shrink: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue