Bläddra i källkod

Ask for consent before enabling Google Analytics and Gauges

Jasper van Merle 6 år sedan
förälder
incheckning
66a0b82e3c

+ 2 - 0
assets/javascripts/app/settings.coffee

@@ -5,6 +5,7 @@ class app.Settings
     'manualUpdate'
     'fastScroll'
     'arrowScroll'
+    'analyticsConsent'
     'docs'
     'dark'
     'layout'
@@ -26,6 +27,7 @@ class app.Settings
     news: 0
     manualUpdate: false
     schema: 1
+    analyticsConsent: false
 
   constructor: ->
     @store = new CookieStore

+ 17 - 1
assets/javascripts/lib/page.coffee

@@ -199,5 +199,21 @@ page.track = (fn) ->
   return
 
 track = ->
-  tracker.call() for tracker in trackers
+  consentGiven = Cookies.get('analyticsConsent')
+  consentAsked = Cookies.get('analyticsConsentAsked')
+
+  if consentGiven == '1'
+    tracker.call() for tracker in trackers
+  else if consentGiven == undefined and consentAsked == undefined
+    # Only ask for consent once per browser session
+    Cookies.set('analyticsConsentAsked', '1')
+
+    new app.views.Notif 'AnalyticsConsent', autoHide: null
+  return
+
+@resetAnalytics = ->
+  for cookie in document.cookie.split(/;\s?/)
+    name = cookie.split('=')[0]
+    if name[0] == '_'
+      Cookies.expire(name)
   return

+ 6 - 0
assets/javascripts/templates/notif_tmpl.coffee

@@ -68,3 +68,9 @@ app.templates.notifShare = ->
 app.templates.notifUpdateDocs = ->
   textNotif """ Documentation updates available. """,
             """ <a href="/offline">Install them</a> as soon as possible to avoid broken pages. """
+
+app.templates.notifAnalyticsConsent = ->
+  textNotif """ Tracking cookies """,
+            """ We would like to gather usage data about how you use DevDocs through Google Analytics and Gauges. We only collect anonymous traffic information.
+                 Please confirm if you accept our tracking cookies. You can always change your decision in the settings.
+                 <br><span class="_notif-right"><a href="#" data-behavior="accept-analytics">Accept</a> or <a href="#" data-behavior="decline-analytics">Decline</a></span> """

+ 2 - 1
assets/javascripts/templates/pages/about_tmpl.coffee

@@ -73,7 +73,8 @@ app.templates.aboutPage = -> """
   <ul>
     <li><a href="https://devdocs.io">devdocs.io</a> ("App") is operated by <a href="https://www.freecodecamp.org/">freeCodeCamp</a> ("We").
     <li>We do not collect personal information through the app.
-    <li>We use Google Analytics, Gauges and Sentry to collect anonymous traffic information and improve the app.
+    <li>We use Google Analytics and Gauges to collect anonymous traffic information if you have given consent to this. You can change your decision in the <a href="/settings">settings</a>.
+    <li>We use Sentry to collect crash data and improve the app.
     <li>The app uses cookies to store user preferences.
     <li>By using the app, you signify your acceptance of this policy. If you do not agree to this policy, please do not use the app.
     <li>If you have any questions regarding privacy, please email <a href="mailto:privacy@freecodecamp.org">privacy@freecodecamp.org</a>.

+ 4 - 0
assets/javascripts/templates/pages/settings_tmpl.coffee

@@ -15,6 +15,10 @@ app.templates.settingsPage = (settings) -> """
         <input type="checkbox" form="settings" name="layout" value="_sidebar-hidden"#{if settings['_sidebar-hidden'] then ' checked' else ''}>Automatically hide and show the sidebar
         <small>Tip: drag the edge of the sidebar to resize it.</small>
       </label>
+      <label class="_settings-label">
+        <input type="checkbox" form="settings" name="analyticsConsent"#{if settings.analyticsConsent then ' checked' else ''}>Enable tracking cookies
+        <small>With this checked, we enable Google Analytics and Gauges to collect anonymous traffic information.</small>
+      </label>
     </div>
   </div>
 

+ 27 - 23
assets/javascripts/tracking.js

@@ -1,28 +1,32 @@
 try {
-  if (app.config.env == 'production') {
-    (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','https://www.google-analytics.com/analytics.js','ga');
-    ga('create', 'UA-5544833-12', 'devdocs.io');
-    page.track(function() {
-      ga('send', 'pageview', {
-        page: location.pathname + location.search + location.hash,
-        dimension1: app.router.context && app.router.context.doc && app.router.context.doc.slug_without_version
+  if (app.config.env === 'development') {
+    if (Cookies.get('analyticsConsent') === '1') {
+      (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','https://www.google-analytics.com/analytics.js','ga');
+      ga('create', 'UA-5544833-12', 'devdocs.io');
+      page.track(function() {
+        ga('send', 'pageview', {
+          page: location.pathname + location.search + location.hash,
+          dimension1: app.router.context && app.router.context.doc && app.router.context.doc.slug_without_version
+        });
       });
-    });
 
-    page.track(function() {
-      if (window._gauges)
-        _gauges.push(['track']);
-      else
-        (function() {
-          var _gauges=_gauges||[];!function(){var a=document.createElement("script");
-          a.type="text/javascript",a.async=!0,a.id="gauges-tracker",
-          a.setAttribute("data-site-id","51c15f82613f5d7819000067"),
-          a.src="https://secure.gaug.es/track.js";var b=document.getElementsByTagName("script")[0];
-          b.parentNode.insertBefore(a,b)}();
-        })();
-    });
+      page.track(function() {
+        if (window._gauges)
+          _gauges.push(['track']);
+        else
+          (function() {
+            var _gauges=_gauges||[];!function(){var a=document.createElement("script");
+              a.type="text/javascript",a.async=!0,a.id="gauges-tracker",
+                a.setAttribute("data-site-id","51c15f82613f5d7819000067"),
+                a.src="https://secure.gaug.es/track.js";var b=document.getElementsByTagName("script")[0];
+              b.parentNode.insertBefore(a,b)}();
+          })();
+      });
+    } else {
+      resetAnalytics();
+    }
   }
 } catch(e) { }

+ 8 - 0
assets/javascripts/views/content/settings_page.coffee

@@ -17,6 +17,7 @@ class app.views.SettingsPage extends app.View
     settings.dark = app.settings.get('dark')
     settings.smoothScroll = !app.settings.get('fastScroll')
     settings.arrowScroll = app.settings.get('arrowScroll')
+    settings.analyticsConsent = app.settings.get('analyticsConsent')
     settings[layout] = app.settings.hasLayout(layout) for layout in LAYOUTS
     settings
 
@@ -42,6 +43,11 @@ class app.views.SettingsPage extends app.View
     app.settings.set('fastScroll', !enable)
     return
 
+  toggleAnalyticsConsent: (enable) ->
+    app.settings.set('analyticsConsent', if enable then '1' else '0')
+    resetAnalytics() unless enable
+    return
+
   toggle: (name, enable) ->
     app.settings.set(name, enable)
     return
@@ -85,6 +91,8 @@ class app.views.SettingsPage extends app.View
         @toggleSmoothScroll input.checked
       when 'import'
         @import input.files[0], input
+      when 'analyticsConsent'
+        @toggleAnalyticsConsent input.checked
       else
         @toggle input.name, input.checked
     return

+ 7 - 5
assets/javascripts/views/layout/document.coffee

@@ -75,9 +75,11 @@ class app.views.Document extends app.View
     return unless target.hasAttribute('data-behavior')
     $.stopEvent(event)
     switch target.getAttribute('data-behavior')
-      when 'back'         then history.back()
-      when 'reload'       then window.location.reload()
-      when 'reboot'       then app.reboot()
-      when 'hard-reload'  then app.reload()
-      when 'reset'        then app.reset() if confirm('Are you sure you want to reset DevDocs?')
+      when 'back'               then history.back()
+      when 'reload'             then window.location.reload()
+      when 'reboot'             then app.reboot()
+      when 'hard-reload'        then app.reload()
+      when 'reset'              then app.reset() if confirm('Are you sure you want to reset DevDocs?')
+      when 'accept-analytics'   then Cookies.set('analyticsConsent', '1') && app.reboot()
+      when 'decline-analytics'  then Cookies.set('analyticsConsent', '0') && app.reboot()
     return

+ 4 - 0
assets/stylesheets/components/_notif.scss

@@ -134,3 +134,7 @@
 
   ._notif-info { color: var(--textColorLight); }
 }
+
+._notif-right {
+  float: right;
+}