Cookie consent (alpha release)
Configure cookie consent to comply with regulatory requirements.
Important
The materials on this website are purely informative and represent a personal view; they do not constitute legal or other professional advice. Consult your professional adviser for legal or other advice.
Caution
The support for cookie consent is still in alpha-stage of development by the Hinode team. As a result, the implementation is subject to change.
Regulations such as GDPR (in the EU and UK) and CCPA/CPRA (California) require consent from users about the use of cookies. Without prior consent, the website should refrain from storing or accessing any cookies, unless they are absolutely essential. Site owners should also be able to share proof of the consents (consent logging) on request of the authorities. Lastly, certain countries put restrictions on where to geographically store the consent logs.
Since release v0.27.0-alpha9 Hinode provides support to simplify the integration with cookie consent managers. Cookie consent management itself is not offered by Hinode, but should be relatively easy to implement by integrating with a third-party solution. Review the next paragraphs to familiarize yourself with the available options and configurations.
Modern websites typically use a combination of local storage, session storage, and cookies to collect and store data. Although the various laws and regulations are commonly referred to as cookie law, the legislation is applicable to all kinds of technologies that enable data collection and processing. In practice, we should look into the scripts that interact with these data storages. Assigning a Hinode script (or a script bundle) to a specific category informs users about their intent.
Important
The available categories and their descriptions are used for illustrative purposes only. It is the responsibility of the site administrator to assign scripts to the correct category.
Hinodes supports the following categorization of scripts and their intent:
other
by default. Any cookies used by these scripts should be reviewed and assigned to a specific category by the site administrator. Hinode also assigns scripts to this category that do not necessarily interact with cookies at all.Hinodes uses modules to include features and functionality as needed. This reduces overhead and improves performance. By assigning a module to an available category, all of the scripts contained within that module are linked to the specified intent. The following example shows the default configuration of the Google Analytics module. You can override these settings in your site’s parameters.
[params.modules.GoogleAnalytics]
integration = "core"
state = "async"
category = "analytics"
You can include modules on all pages or include them on specific pages only. For example, Bootstrap is a module that is required by all pages. On the other hand, the Leaflet module is only required when displaying an interactive map. The module’s scripts are often loaded lazily to improve the site performance. They are included at the bottom of the rendered HTML page. Hinode also includes several scripts that impact the user’s experience. These scripts initialize the preferred theme and language and are critical for the initial rendering. As such, these critical scripts are included in the page’s header.
Hinode uses the following naming conventions for each type of script:
assets/js/critical
folder are bundled into a single file called /js/critical.bundle.min.js
.other
, the suffix is omitted. Localized modules (such as FlexSearch) trigger a language code extension.The following example illustrates the files as used by the
components page on the demo site
. This page loads
Leaflet
,
Lottie
, and
Simple Datatables
as optional modules. It inludes
Google Analytics
as core module assigned to the analytics
category. The integrity hashes have been omitted for clarity.
<!doctype html>
<html lang=en class=no-js>
<head>
<script src=/js/critical.bundle.min.js></script>
</head>
<body>
[...]
<script src=/js/core.bundle-analytics.en.min.js data-category=analytics async></script>
<script src=/js/core.bundle.en.min.js async></script>
<script src=/js/leaflet.min.js></script>
<script src=/js/lottie.min.js></script>
<script src=/js/simple-datatables.js async></script>
</body>
</html>
Hinode includes a partial template to render the script references. It is invoked for each generated script bundle (see the previous section). You can use the template to customize the script references. The following variables are available within the template as such:
Name | Type | Required | Default | Comment |
---|---|---|---|---|
category | select | other | Assigns the script to a category that can be used for cookie consent management. Supported values: [necessary, functional, analytics, performance, advertisement, other]. | |
integrity | string | Cryptographic hash of the script to enable Subresource Integrity (SRI). | ||
link | string | yes | Location of the script source, either an URL for an external script or a (relative) path for a local script. | |
state | select | Defines the loading behavior of the script bundle. By default, scripts are loaded immediately. Use async to process the script in the background. Use defer to load the script in relative order when the DOM is fully built. Supported values: [async, defer, immediate]. |
Hinode includes a basic script template in layouts/partials/templates/script.html
. It includes the following code:
<!--
Copyright © 2024 The Hinode Team / Mark Dumay. All rights reserved.
Use of this source code is governed by The MIT License (MIT) that can be found in the LICENSE file.
Visit gethinode.com/license for more details.
-->
<!-- Initialize arguments -->
{{ $args := partial "utilities/InitArgs.html" (dict "structure" "script" "args" .) }}
{{ if $args.err }}
{{ partial "utilities/LogErr.html" (dict
"partial" "templates/script.html"
"msg" "Invalid arguments"
"details" $args.errmsg
"file" page.File
)}}
{{ end }}
<!-- Initialize local arguments -->
{{ $category := cond (ne $args.category "other") $args.category "" }}
<!-- Main code -->
<script src="{{ $args.link }}"
{{- with $category }} data-category="{{ . }}"{{ end -}}
{{- with $args.integrity }}integrity="{{ . }}" crossorigin="anonymous"{{ end }}
{{- with $args.state }} {{ . | safeHTMLAttr }}{{ end -}}>
</script>
You can modify this template to your needs. For example,
CookieYes supports a custom attribute
called data-cookieyes
to categorize the referenced script. You could modify the template to include this custom attribute:
[...]
<script src="{{ $args.link }}"
{{- with $category }} data-cookieyes="cookieyes-{{ . }}"{{ end -}}
{{- with $args.integrity }}integrity="{{ . }}" crossorigin="anonymous"{{ end }}
{{- with $args.state }} {{ . | safeHTMLAttr }}{{ end -}}>
</script>
Hinode uses several script to access and store the user’s preferences, including the selected theme and language. Instead of assigning an entire script or script bundle to a category, you can also use predefined APIs. These APIs will give you fine-grained control on when to invoke a cookie consent check. Use the get*
and set*
functions to interact with the local storage and session storage respectively. The hasConsent()
function is a placeholder that should be hooked to your cookie consent manager of choice.
The available functions are defined in /assets/js/critical/_cookie.js
:
/* eslint-disable no-undef, no-unused-vars */
function hasConsent (category) {
// TODO: placeholder function
return true
}
function getLocalStorage (key, def, category) {
if (hasConsent(category)) {
return localStorage.getItem(key)
} else {
return def
}
}
function setLocalStorage (key, val, category) {
if (hasConsent(category)) {
localStorage.setItem(key, val)
}
}
function getSessionStorage (key, def, category) {
if (hasConsent(category)) {
return sessionStorage.getItem(key)
} else {
return def
}
}
function setSessionStorage (key, val, category) {
if (hasConsent(category)) {
sessionStorage.setItem(key, val)
}
}