digitoimistodude/air-cookie

Simple cookie banner and management.

Installs: 245

Dependents: 0

Suggesters: 0

Security: 0

Stars: 10

Watchers: 3

Forks: 1

Open Issues: 3

Type:wordpress-plugin

1.2.7 2024-03-14 11:41 UTC

This package is auto-updated.

Last update: 2024-04-14 11:51:42 UTC


README

Packagist CookieConsent_Version Tested_up_to WordPress_6.4.3 Compatible_with PHP_8.3 Build

Air cookie provides simple cookie banner and management.

Uses the CookieConsent javascript plugin as a base, making its usage with WordPress easier.

Features

  • Simple and lightweight cookie banner
  • Third party embeds blocking until cookies accepted
  • Easy to load scripts and execute custom javascript when cookies are accepted
  • Support for multiple different cookie categories
  • Polylang support for multilingual websites
  • Visitor consent recording
  • Cookie categories revision control

Usage

Link to cookie settings

Remember to add a link into the footer, which allows opening the cookie settings anytime!

<a href="#" data-cc="c-settings" class="cc-link">Cookie settings</a>

If you have Polylang installed and active, use

<a href="#" data-cc="c-settings" class="cc-link">
  <?php echo pll_translate_string( 'Evästeasetukset', pll_current_language() ); ?>
</a>

Cookie categories

By default, plugin has two cookie categories necessary, functional and analytics. You may add new categories with air_cookie\categories filter like shown below.

add_filter( 'air_cookie\categories', 'my_add_cookie_category' );
function my_add_cookie_category( $categories ) {
  $categories[] = [
    'key'         => 'ads',
    'enabled'     => false, // it is advised to have categories disabled by default
    'readonly'    => false, // user should have always control over categories
    'title'       => 'Ads',
    'description' => 'This site uses external services to display ads, and they might set some cookies.',
  ];

  return $categories;
}

When adding new categories, the function itself is responsile for handling the translations for title and description.

There is also air_cookie\categories\{category-key} filter available to change the settings of indivual category.

Loading scripts after cookies have been accepted

The easiest way to load external script is by altering the script tag to be:

<script type="text/plain" data-src="<uri-to-script>" data-cookiecategory="analytics" defer>

The example above works only, if the script does not require any extra javascript to be executed after the script has been loaded. If you need to execute extra javascript, use the example below.

add_action( 'air_cookie_js_analytics', 'my_add_js_for_analytics' );
function my_add_js_for_analytics() {
  ob_start(); ?>
    cc.loadScript( 'https://www.google-analytics.com/analytics.js', function() {
      ga('create', 'UA-XXXXXXXX-Y', 'auto');  //replace UA-XXXXXXXX-Y with your tracking code
      ga('send', 'pageview');
    } );
  <?php echo ob_get_clean();
}

Google Tag Manager (gtm.js)

add_action( 'air_cookie_js_analytics', 'my_add_js_for_analytics' );
function my_add_js_for_analytics() {
  ob_start(); ?>
    (function (w, d, s, l, i) {
      w[l] = w[l] || [];
      w[l].push({ "gtm.start": new Date().getTime(), event: "gtm.js" });
      var f = d.getElementsByTagName(s)[0],
        j = d.createElement(s),
        dl = l != "dataLayer" ? "&l=" + l : "";
      j.async = true;
      j.src = "https://www.googletagmanager.com/gtm.js?id=" + i + dl;
      f.parentNode.insertBefore(j, f);
    })(window, document, "script", "dataLayer", "GTM-XXXXXX");
  <?php echo ob_get_clean();
}

Google Tag Manager (gtag.js)

add_action( 'air_cookie_js_analytics', 'my_add_js_for_analytics' );
function my_add_js_for_analytics() {
  ob_start(); ?>
    cc.loadScript( 'https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXXX-X', function() {
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', 'UA-XXXXXXXXX-X');
    });
  <?php echo ob_get_clean();
}

Google Analytics (analytics.js)

add_action( 'air_cookie_js_analytics', 'my_add_js_for_analytics' );
function my_add_js_for_analytics() {
  ob_start(); ?>
    cc.loadScript( 'https://www.google-analytics.com/analytics.js', function() {
      ga('create', 'UA-XXXXXXXX-Y', 'auto');  //replace UA-XXXXXXXX-Y with your tracking code
      ga('send', 'pageview');
    } );
  <?php echo ob_get_clean();
}

Moving plugin javascript to be loaded after cookies have been accepted

// Disable script by nulling the tag on latest possible chance
add_filter( 'script_loader_tag', function( $tag, $handle ) {
  if ( 'our-script-handle' === $handle ) {
    return '';
  }

  return $tag;
}, 10, 2 );

// Load stamped.io script on air cookie
add_action( 'air_cookie_js_functional', function() {
  $stampedio_url = get_script_src_by_handle( 'our-script-handle' );
  if ( empty( $stampedio_url ) ) {
    return;
  }

  ob_start(); ?>
    cc.loadScript( '<?php echo esc_url( $stampedio_url ) ?>' );
  <?php echo ob_get_clean(); // phpcs:ignore
} ); // end woocommerce_ga_integration_script_for_air_cookie

function get_script_src_by_handle( $handle ) {
  global $wp_scripts;
  if ( in_array( $handle, $wp_scripts->queue ) ) {
    return $wp_scripts->registered[ $handle ]->src;
  }
} // end get_script_src_by_handle

// Disable stamped.io script by nulling the tag on latest possible chance
add_filter( 'script_loader_tag', function( $tag, $handle ) {
  if ( 'woo-stamped-io-public-custom' === $handle ) {
    return '';
  }

  return $tag;
}, 10, 2 );

// Load stamped.io script on air cookie
add_action( 'air_cookie_js_functional', __NAMESPACE__ . '\woocommerce_stampedio_script_for_air_cookie' );
function woocommerce_stampedio_script_for_air_cookie() {
  $stampedio_url = get_script_src_by_handle( 'woo-stamped-io-public-custom' );
  if ( empty( $stampedio_url ) ) {
    return;
  }

  ob_start(); ?>
    cc.loadScript( '<?php echo esc_url( $stampedio_url ) ?>' );
  <?php echo ob_get_clean(); // phpcs:ignore
} // end woocommerce_ga_integration_script_for_air_cookie

Executing custom javascript after cookies have been accepted

You may execute your own javascript after certain cookie categories have been accepted. There are two ways of doing that: adding the javascript inline to header or using custom javascript events.

Adding the javascript inline

Each cookie category do get its own action, from which javascript can be outputted to be added in the main header script tag.

add_action( 'air_cookie_js_<category-key>', 'my_add_js_for_<category-key>' );
function my_add_js_for_<category-key>() {
  ob_start(); ?>
    console.log( 'Hello world!' );
  <?php echo ob_get_clean();
}

If you wish to use your own script tag, it is possible with example below

<script type="text/plain" data-cookiecategory="<category-key>">
  console.log( 'Hello world!' );
</script>

In separate javascript file

If you have custom javascript files in which you need to exceute code only after certain categories are accepted, there is custom javascript events available.

Each cookie category do get its own event, to which you can bind event listener into.

document.addEventListener( 'air_cookie_<category-key>', (event) => {
  console.log( 'Hello world!' );
} );

There is also a global custom event available, in which the category key is passed as an detail.

document.addEventListener( 'air_cookie', (event) => {
  console.log( 'Hello world! The category is ' + event.detail.category );
} );

Changing settings

Setting names do follow the CookieConsents option names. Some settings defaults are set to be different than the CookieConsent defaults:

Setting Value
cookie_name air_cookie
current_lang value from polylang or locale option
revision automatically calculated from cookie categories
page_scripts true
gui_options/consent_modal/layout box
gui_options/consent_modal/position bottom left

You may change the settings with air_cookie\settings filter which contains all settings or air_cookie\settings\{setting-name} filter for indivual setting.

add_filter( 'air_cookie\settings', 'my_modify_cc_settings' );
function my_modify_cc_settings( $settings ) {
  $settings['page_scripts'] = false;
  return $settings;
}
add_filter( 'air_cookie\settings\page_scripts', 'my_modify_cc_setting_page_scripts' );
function my_modify_cc_setting_page_scripts( $setting ) {
  return false;
}

Note that these filters do not* contain the strings or cookie categories. The air_cookie\settings_all filter contains everyhing, but usage is highly disencouraged as everything has their own specific filter.

Modifying default strings

If there is a need to modify default strings, the most preferred way to chage those is via Polylang string translations. To change the strings for all languages, it is not required to change the source.

In case of Polylang not being used, there is air_cookie\strings filter which contains all strings and air_cookie\strings\{string-key} filters for indivual strings.

add_filter( 'air_cookie\strings', 'my_modify_cc_strings' );
function my_modify_cc_strings( $strings ) {
  $strings['consent_modal_title'] = 'Have a cookie?';
  return $strings;
}
add_filter( 'air_cookie\strings\consent_modal_title', 'my_modify_cc_string_consent_modal_title' );
function my_modify_cc_string_consent_modal_title( $string ) {
  return 'Have a cookie?';
}

Third party embeds blocking

By default third party embeds blocking is active and all embeds for following services are blocked: Youtube, Vimeo, Instagram, Facebook, Twitter, Soundcloud, Spotify, Slideshare, WordPress.com Video, Embedly, Issuu, Imgur and TikTok.

Disable this feature with air_cookie\embeds filter by returning false.

add_filter( 'air_cookie\embeds', '__return_false' );

Iframe embeds are replaced with placeholder, letting visitor know that the embed might use tracking cookies. They then have opportunity to allow all cookies or enable the singular embed once.

For script embeds, we just replace the src tag with data-src and add data-cookiecategory which makes those to work CookieConsents way of loading scripts.

Cookie category for embeds

When the feature is enabled, a new cookie category is added. When this category is accepted, all embeds are loaded and shown.

Use strings filter air_cookie\strings to modify the texts for this category.

Thumbnails for placeholders

Iframe embed placeholders do support thumbnails. Without a thumbnail, the iframe is replaced with black background box. Youtube and Vimeo embeds do get automatically the placeholder.

For other services, you may use air_cookie\embeds\thumbnail filter like shown below.

add_filter( 'air_cookie\embeds\thumbnail', 'my_maybe_add_thumbnail', 10, 2 );
function my_maybe_add_thumbnail( $thumbnail, $src ) {
  // If thumbnail is already set, bail.
  if ( ! empty( $thumbnail ) ) {
    return $thumbnail;
  }

  // Do your magic to get the thumbnail

  return 'https://your.thumbna.il/location.jpg';
}

Vimeo and Do Not Track

Vimeo embeds are treated a bit differently. For those, we don't add placeholder nor block them. Instead, we add Do Not Track parameter for the embed src which disabled all Vimeo tracking and statistics.

Disable this feature with air_cookie\embeds\vimeo\add_dnt filter, but notice that WordPress Core adds the dnt by default as well.

If you wish to show the placeholder even if the Vimeo embed has Do Not Track enabled, use air_cookie\embeds\vimeo\skip_dnt filter.

Revision control

Cookie policy revision number is automatically calculated from cookie categories key, enabled and readonly values. If new categories are added, some are removed or the values changed the consent modal will be shown again.

In case you wish to have manual control over revision number, use air_cookie\categories\revision filter. First argument is the calculated revision number and second is array containing all current cookie categories.

Visitor consent recording

Finnish cookie law requires the site owner to be able to point when certain visitor has accepted cookies. This is why the plugin has simple visitor consent recording system.

Each visitor is given unique uuid4 ID. When visitor accepts any cookie categories, their browser will send a small request to REST API which records their ID, current revision, accepted cookie categories, timestamp of the event and timestamp of expiry. This data is stored in custom database table and does not contain any extra information about the visitor.

Currently there is no way to disable this feature.

Installing

Download latest version as a zip package and unzip it to your plugins directiry.

Or install with composer, running command composer require digitoimistodude/air-cookie in your project directory or add "digitoimistodude/air-cookie":"dev-master" to your composer.json require.

Updates

Updates will be automatically distributed when new version is released.

Changelog

Changelog can be found from releases page.

Contributing

If you have ideas about the plugin or spot an issue, please let us know. Before contributing ideas or reporting an issue about "missing" features or things regarding to the nature of that matter, please note that this plugin is drafted to fullfill our customers need and might not move into the direction you'd hope. Thank you very much.