Cookie consent
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.
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 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 using the pointers in this section. Review the next paragraphs to familiarize yourself with the available options and configurations.
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.
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. 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 also assign regular scripts and external scripts to an intent category. See the script integration approaches for more details.
Hinode includes a partial template to render the script references. It is invoked for each generated script bundle (see the scripts documentation for more details). 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 scripts 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)
}
}
Pending your cookie consent configuration, the API functions may not be available at all times. The following code illustrates how to test for the availability of the getLocalStorage()
function:
if (typeof getLocalStorage === "function") {
[...]
}
Important
You cannot test the CookieYes integration locally, as CookieYes actively validates the domain name of the host. However, you can set up a staging environment when on a paid plan. See the Staging Mode documentation for more details.
Hinode provides a reference implementation to integrate with CookieYes . CookieYes offers various plans, including a free plan for blogs and personal websites. Once signed up, capture the link to your CookieYes banner script. See the installation code in the advanced settings of your CookieYes account. The code is available by clicking the button next to the cookie banner status. The link has the following pattern:
Include the banner script in your site’s parameters, replacing the {installation code}
with the actual value:
[modules.cookieyes]
url = "https://cdn-cookieyes.com/client_data/{installation code}/script.js"
Next, include the mod-cookieyes
in your module configuration. Please ensure mod-cookieyes
is imported before the hinode
module to ensure the correct script template is initialized. The following snippet illustrates an example configuration for hugo.toml
.
[module]
[[module.imports]]
path = "github.com/gethinode/mod-cookieyes/v2"
[[module.imports]]
path = "github.com/gethinode/hinode"
CookieYes requires several directives to be added to your Content Security Policy. See the policy requirements as provided by CookieYes for more details. The directives should be added to your server headers.