Skip to content

Simple, lightweight and easy-to-implement Cookie/Tracking consent manager for the web

License

Notifications You must be signed in to change notification settings

Accudio/cead-consent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cead Consent Manager

Cead (pronounced kee-yed)is a cookie and tracking consent manager that is extremely simple and lightweight. It is designed to help websites implement a simple Accept or Deny dialog that will actually enable or disable tracking.

Many websites implement a notice that doesn't allow opt-out, some offer an option that does nothing, whilst others only offer an opt-out solution - conveniently after they've collected all of your data. Cead helps you fix this, allowing you to meet your privacy obligations with little effort or code. In opt-in mode, tracking scripts won't even run until consent is given. In opt-out mode withdrawing consent will clear tracking cookies entirely.

Cead is primarily created in response an increase in unsolicited web surveillance, but also to assist with meeting the standards of regulation including the EU GDPR & ePrivacy and California's CCPA. As privacy legislation becomes more strict it's important that solutions offer compliant opt-in and opt-out controls which Cead offers at it's core.

Note: I am not a lawyer, and Cead isn't a magic fix for privacy compliance. When implemented correctly it meets commonly-understood privacy standards, but you may need legal advice for your specific usecase.

Features

  • Simple — Most sites don't need a fancy system with different purposes, just a simple opt-in/opt-out that can be used for all tracking and cookies;
  • Lightweight — Weighs in at just 3.3kB minified and 1.9kB gzip;
  • Flexible — HTML is provided by you so all text and classes are fully configurable, with lots of options on attributes, cookie name and mode in the JavaScript;
  • Standalone — Entirely self-contained, Cead doesn't link with any complex external system or have hundreds of dependencies;
  • Open Source — Free to use, modify and extend as you'd like! Licensed under the permissive Apache-2.0 license.

I wrote a blog post giving an introduction to and basic tutorial getting started with Cead Consent.

Table of Contents

  1. Installation
    1. NPM Install
  2. Managing tracking scripts and images
    1. External Scripts
    2. Inline Scripts
    3. Image Pixels
  3. Managing Cookies
  4. Events
  5. Options
  6. Examples
    1. Google Analytics (gtag.js)
    2. Google Tag Manager
    3. Facebook Pixel
    4. Matomo / Piwik
    5. LinkedIn Insights
    6. Hubspot Analytics
    7. Fathom Analytics
    8. Plausible Analytics
  7. Changelog
  8. License, Copyright and Credits

Installation

The easiest way to install Cead is to link to the browser.js script and cead.css stylesheet, and include the required HTML manually in your document. You can download them from the dist/ folder of the repo or you can use an asset CDN like JSDelivr as below.

<html>
  <head>
    <!-- include the CSS in the <head> of your html -->
    <link rel="stylesheet" href="/cead.css">
    <!--<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cead-consent@1/dist/cead.css">-->
  </head>

  <body>
    <!-- cead required markup, insert before your page content -->
    <!-- you can customise the content of the <p> element and buttons as you'd like, just keep the classes -->
    <div class="cead" role="region" aria-label="Cookie consent">
      <p>Hi! Could we please enable some services and cookies to improve your experience and our website?</p>
      <div class="cead__btns">
        <button class="cead__btn cead__btn--decline">No, thanks.</button>
        <button class="cead__btn cead__btn--accept">Okay!</button>
      </div>
    </div>

    <!-- your page content -->

    <!-- set your options as an object on window.cead before loading cead -->
    <script>
      window.cead = {
        cookie: 'consent'
      }
    </script>
    <!-- include the browser.js file before the closing </body> -->
    <script src="/browser.js"></script>
    <!--<script src="https://cdn.jsdelivr.net/npm/cead-consent@1/dist/browser.js"></script>-->
  </body>
</html>

NPM Install and Import (advanced)

Cead can also be installed via NPM and imported via your build tool.

npm install cead-consent
import Cead from 'cead-consent'
new Cead({
  cookie: 'consent'
})

Default styles are provided in dist/cead.css or source styles in src/sass/cead.scss but you are free to provide your own.

You will need to add your own markup, the below is provided as an example. The only required classes are .cead for the container and .cead__btn--decline & .cead__btn--accept for the buttons.

<div class="cead" role="region" aria-label="Cookie consent">
  <p>Hi! Could we please enable some services and cookies to improve your experience and our website?</p>
  <div class="cead__btns">
    <button class="cead__btn cead__btn--decline">No, thanks.</button>
    <button class="cead__btn cead__btn--accept">Okay!</button>
  </div>
</div>

Managing tracking scripts and images

Cead manages tracking scripts and images by modifying their code slightly so they can only run when Cead allows them to. This will be done instantly if the default: true option is set or the user has already consented, otherwise it will wait until consent is received. The attribute used can be customised with the attr option but defaults to data-cead - which will be used in these examples.

External scripts

Change the src attribute to data-src and add the consent attribute.

<script data-src="https://example.com/tracking.js" data-cead></script>

Inline scripts

Add type="text/plain" to the script tag and add the consent attribute.

<script type="text/plain" data-cead>
  console.log('inline tracking script');
</script>

Image Pixels

Change the src attribute to data-src and add the consent attribute. If this is a tracking pixel that shouldn't be displayed display:none will prevent a missing image icon. If this is to be displayed you can show/hide the image with css as below:

<img data-src="https://example.com/tracking.jpg" data-cead alt="" class="display:none">
img[data-cead]:not([src]) {
  display: none;
}

Managing Cookies

When initialising Cead, you can provide the cookies option, in the form of an array of cookie names. On opt-out, these cookies will be removed, making it more difficult for trackers to link user sessions.

An example using Google Analytics and Facebook pixel:

<script>
window.cead = {
  cookies: [
    '_ga',
    '_gid',
    '_fbp',
    '_fbc'
  ]
}
</script>

Events

For more advanced use-cases you can use Cead's global events to get the tracking state and to watch for changes.

All events provide a status property on the event detail which will be true or false depending on the consent status.

Events available:

  • cead:ready — On initialisation of Cead, after activate/deactivate functionality
  • cead:change — On click of either the accept or decline button

Example implementation:

// watch for ready
window.addEventListener('cead:ready', e => {
  console.log('cead ready. status:', e.detail.status)
})

// on click
window.addEventListener('cead:change', e => {
  console.log('cead change. new status:', e.detail.status)
})

Options

For the browser version, options are set on window.cead before loading the script. For the npm version, pass an options object in when calling new Cead({}).

All options available:

Option name Default value Description
default false Default state for tracking when a user hasn't made a consent decision. Set to true for opt-out mode.
cookie cead Name of the cookie that stores Cead preferences
attr data-cead Attribute set on tracking elements
srcAttr data-src Attribute for script src. You may need to change this if you use other libraries that use data-src
link #cead Cead will open the consent manager when links with this href are clicked.
cookies [] Array of cookies to remove on opt-out.

Examples

Here are some of the major analytics/tracking scripts modified to work with Cead using default options. These are based on the provided code at time of writing but may change. You should be able to modify any tracking script and image to a format Cead will be able to control. If you have any problems doing so file an Issue and I can take a look.

Google Analytics (gtag.js)

Replace GA_MEASUREMENT_ID with your Analytics ID provided by Google.

Script Tag:

<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'GA_MEASUREMENT_ID', {
  'send_page_view': true,
  'anonymize_ip': true
});
</script>
<script async data-src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID" data-cead></script>

Cookies: '_ga', '_gid'

Google Tag Manager

Replace GTM_MEASUREMENT_ID with your Tag Manager ID provided by Google.

Script Tag:

<script>
dataLayer=[];
(function(w,l){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'})})(window,'dataLayer');
</script>
<script async data-src="https://www.googletagmanager.com/gtm.js?id=GTM_MEASUREMENT_ID&l=dataLayer" data-cead></script>

Cookies (will depend on tags loaded): '_ga', '_gid'

Facebook Pixel

Replace FB_PIXEL_ID with your Pixel ID provided by Facebook.

Script Tag:

<script>
!function(f,n){if(f.fbq){return}n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq){f._fbq=n}n.push=n;n.loaded=!0;n.version='2.0';n.queue=[]
}(window);fbq('init','FB_PIXEL_ID');fbq('track', 'PageView');
</script>
<script async data-src="https://connect.facebook.net/en_US/fbevents.js" data-cead></script>

Cookeis: '_fbp', '_fbc'

Matomo / Piwik

Replace MATOMO_URL and MATOMO_SITE to the URL and Site ID provided by your Matomo install.

Script Tag:

<script>
var _paq = window._paq = window._paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="MATOMO_URL/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', MATOMO_SITE]);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.setAttribute('data-src', u+'matomo.js');g.setAttribute('data-cead', 'true');
g.async=true;s.parentNode.insertBefore(g,s);
})();
</script>

Cookies: '_pk_ref', '_pk_cvar', '_pk_id', '_pk_ses', '_pk_hsr'

LinkedIn Insights

Replace LI_PARTNER_ID with your LinkedIn Partner ID.

Script Tag:

<script>_linkedin_data_partner_id = "LI_PARTNER_ID";</script>
<script async data-src="https://snap.licdn.com/li.lms-analytics/insight.min.js" data-cead></script>

Cookies: 'li_fat_id'

Hubspot Analytics

Replace HS_TRACKING_ID with your Hubspot tracking ID.

Script Tag:

<script id="hs-script-loader" async data-src="https://js.hs-scripts.com/HS_TRACKING_ID.js" data-cead></script>

Cookies: '__hstc', '__hssc', '__hssrc'

Fathom Analytics

Replace FATHOM_URL with the Script URL provided by Fathom and FATHOM_SITE with your Fathom site ID.

Script Tag:

<script
  async data-cead
  data-src="FATHOM_URL"
  data-site="FATHOM_SITE"
  data-honor-dnt="true"
></script>]

Plausible Analytics

Replace PLAUSIBLE_SRC and PLAUSIBLE_DOMAIN with the code source and domain provided by Plausible.

Script Tag:

<script>
(function() {
var tag = document.createElement('script');
tag.async = true;
tag.setAttribute("data-src","PLAUSIBLE_SRC");
tag.setAttribute("data-cead", "true");
tag.setAttribute("data-domain", "PLAUSIBLE_DOMAIN");
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
})();
</script>

Changelog

  • 1.1.4 - Added SameSite=Lax to Cead cookie
  • 1.1.3 — Changed dependencies for devDependencies to prevent unnecessary installs when installed in another project
  • 1.1.2 — Changed default files in package.json to fix webpack + jsdelivr support
  • 1.1.1 — Updated README with correct gtag.js example
  • 1.1.0 — Adds custom events, making it a little easier for advanced integrations
  • 1.0.1 — Readme and docs update
  • 1.0.0 — First stable release and npm publish
  • 0.1.0 — Initial development version (August 2021)

License, Copyright and Credits

This project is licensed under the Apache-2.0 license.

The full license is included at LICENSE.md, or at apache.org/licenses/LICENSE-2.0.

Copyright © 2021 Alistair Shepherd.