Cookieman

Version

main

Language

en

Authors

Jonas Eberle, Sebastian Klein

Email

projekt-cookieman@d-mind.de

License

This extension documentation is published under the CC BY-NC-SA 4.0 (Creative Commons) license

TYPO3

The content of this document is related to TYPO3 CMS, a GNU/GPL CMS/Framework available from typo3.org .

Community Documentation:

This documentation is community documentation for the TYPO3 extension 'cookieman'.

It is maintained as part of this third party extension.

If you find an error or something is missing, please: Report a Problem

Extension Manual

This documentation is for the TYPO3 extension 'cookieman'.

Contributing To This Manual

You are welcome to help improve this guide. Just click on "Edit me on GitHub" on the top right to submit your change request.

For contributing code, see the section Contributing.

Sitemap

Sitemap

For Developers

Sitemap

Introduction

What does it do?

It provides a user consent popup. It asks for approval to include tracking objects (cookies, images or any HTML) and includes the objects when consented.

It allows tracking from the very first page (including referrer).

Consents are managed in groups and saved to a cookie.

It provides a stable API to work with in JavaScript.

It removes HTML-cookies of tracking objects after the user has revoked consent.

When is the popup shown to users?

By default, the popup is shown once on every page load until the user saves the consent status.

The consent status is saved in the cookie CookieConsent.

Does the user have to make a choice?

In our demo themes, we allow closing the popup without forcing the user to make a selection by clicking outside of the modal popup or using the ESC key. In that case no consent is saved, thus the popup is shown again upon opening another page.

This behaviour is to follow our interpretation of the GDPR that a consent decision should not be forced. Bullet point 82 in Guidelines 05/2020 of the European Data Protection Board reads:

When consent is to be given following a request by electronic means, the request for consent should not be unnecessarily disruptive to the use of the service for which the consent is provided (See Recital 32 GDPR). An active affirmative motion by which the data subject indicates consent can be necessary when a less infringing or disturbing modus would result in ambiguity. Thus, it may be necessary that a consent request interrupts the use experience to some extent to make that request effective.

Since websites can continue to work without a consent, we think users should be given the possibility of just looking around without any consent. We don't see any ambiguity if no decission has been taken: The default is a continued service under the common rules "data minimisation + no third party involved".

Of course, any functionality that requires consent has to be disabled in that case ("fallback gracefully" where possible).

Features

  • Tracking objects: Render detailed information about your cookies, tracking pixels, LocalStorage entries...: Name, Purpose, Lifetime, Type, Provider
  • Tracking objects: Commonly used tracking objects are already supported with configuration and information text
  • Tracking objects: Extendable as needed
  • Tracking objects: HTML Cookies will be removed from the user's browser
  • Groups: Group your tracking objects (e.g. "Mandatory", "Marketing", "Analytics")
  • Groups: Preselect and/or disable groups, e.g. the group for mandatory technical cookies
  • A note about the "Do-not-track" setting can be shown inside the popup and this setting can also be respected (configurable on a per-group level)
  • The extension includes 3 ready-made themes based on Bootstrap
  • Customization: Fluid templates and all texts can be adjusted to your needs

Compatibility

  • Supports all modern browsers
  • Can be configured to work with a strict Content Security Policy (no inline scripts are needed)

Demo

You can click around the included demo themes here. Have a look at the JavaScript console to see when tracking gets enabled.

You can also try out the "Do-not-track" setting of your browser which triggers a message inside the popup (in the "marketing" group) when enabled.

Screenshots

(Click on the screenshots to open the full resolution.)

Showcase of a site implementation

Showcase of a site implementation

Showcase of a site implementation

Installation

Target group: Administrators

Requirements

  • If you reimplement your own theme, it has no requirements at all
  • for the example themes:

    • Bootstrap 3/4/5 CSS
    • Bootstrap 3/4/5 JavaScript for collapse and modal
    • jQuery
  • we also apreciate new and creative custom themes

Installation

  1. Get the extension:

    1. From the Extension Manager: Open the Extension Manager module in the TYPO3 backend and choose 'Get extensions'. Search for the extension key cookieman. Click on the extension title to get a list of all available versions. Import and install the version which is compatible to your TYPO3 version.
    2. From the TYPO3 Extension Repository (TER): You can download ZIP archives of different versions from https://extensions.typo3.org/extension/cookieman. Upload the file afterwards in the Extension Manager.
    3. With composer: Use composer req dmind/cookieman. This will load a compatible version available from Packagist.
  2. Integration: Include the static TypoScript "Cookieman" in your root template or reference the necessary files in your site package. This will get you a group mandatory with the tracking object CookieConsent.

    For evaluation purposes: Include the static TypoScript "Cookieman (Example configuration of groups and tracking objects)" to see a full example with multiple groups and tracking objects.

  3. Configure the extension with TypoScript constants and setup (see Usage of cookies).

Configuration

Target group: Developers, Integrators

This extension comes with two static templates:

  • Cookieman contains the basic and necessary configuration. Use this and extend the settings to your needs.
  • Cookieman (Example configuration of groups and tracking objects) can be included additionally to get a full example with multiple groups and tracking objects.

Learn how to configure Cookieman:

Usage of cookies

Target group: Developers, Integrators

Find out which tracking objects are used

You can check your page with an empty cookie storage with your browser and see which cookies gets inserted in your browser. Or you can use a service like Cookieservice to fetch a page or sign up for services that crawl your whole site regularly for cookies.

There might be connections made to external servers to access tracking pixels or other content that warrant a user consent, too. This applies to YouTube (use youtube-nocookie.com) and CDNs (Google Fonts, Bootstrap and other frontend libraries - recommendation: do not use external connections at all if not necessary).

Also other means for tracking might be used, like HTML5 Web Storage (localStorage). It is a task for the official Data Security Officer of the site to decide what needs to be consented. If done correctly, you should be able to find a note about used tracking services in the Data Privacy Statement of the website.

If you have control over how the tracking object is inserted you can have Cookieman handle that for you. Otherwise you can make the actual inclusion of the tracking object dependent on a Cookieman-API-call or a presence of a certain string in Cookieman's cookie "CookieConsent" - this is recommended if you are managing several tags with Google Tag Manager (set its trigger to "cookie ‹CookieConsent› contains ‹group name, e.g. "marketing"›).

Configuration example

Target group: Developers, Integrators

Example

This example configuration is based on the base TypoScript configuration (see Installation) without the example template.

# include definition of TrackingObjects
@import 'EXT:cookieman/Configuration/TypoScript/TrackingObjects/*.typoscript'

plugin.tx_cookieman.settings {
    trackingObjects {
        # extend the existing configuration for 'Matomo'
        Matomo {
            inject >
            inject (
            <script type="text/javascript">
              var _paq = window._paq || [];
              _paq.push(['trackPageView']);
              _paq.push(['enableLinkTracking']);
              (function() {
                var u="//my-piwik-server.my-domain.com/";
                _paq.push(['setTrackerUrl', u+'matomo.php']);
                _paq.push(['setSiteId', 'my site ID']);
                var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
                g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
              })();
            </script>
            )
        }

        # add my own custom tracking solution
        # if you have a useful configuration and want to share, we would be happy if you did a pull request!
        MyOwnTrackingPixel {
            inject = TEXT
            inject {
                insertData = 1
                value = (
                    <div>Here be dragons <img src="/{path : EXT:my_ext/Resources/Public/Image/MyImage.png}?{date : U}"></div>
                    <script>alert('oh la la!')</script>
                )
            }
            show {
                # each element here represents one line of information in the consent popup
                pixelphp {
                    duration = 1
                    durationUnit = months
                    type = pixel
                    provider = My Website Inc.
                }
            }
        }
    }

    groups {
        # my new group
        mygroup {
            trackingObjects {
                0 = Matomo
                1 = MyOwnTrackingPixel
            }

             respectDnt = 1
             showDntMessage = 1

        }
    }
}

plugin.tx_cookieman._LOCAL_LANG {
    en {
        trackingobject\.pixelphp = You can translate the name, but you do not have to.
        trackingobject\.pixelphp\.desc = My own tracking pixel does not really track you. It's just here to cheer you up.
        group\.mygroup = My group is my castle.
        type\.pixel = Tracking pixel
    }
    default < .en
}
Copied!

TypoScript constants

Adjust the TypoScript constants (again, either in a sys_template record or in a file in your site package).

All constants are prepended with plugin.tx_cookieman.settings.

resourcesBasePath

resourcesBasePath

| Data type: data-type-path | Default: EXT:cookieman/Resources | Example: EXT:mysitepackage/Resources |

Path to directory that holds the themes. Default enables the shipped demo themes. See Custom themes how to create a new theme.

theme

theme

| Data type: data-type-string | Default: bootstrap4-modal | Example: my-theme |

Name of the theme. It is used to extend the resourcesBasePath to create the full path to templates and assets.

The shipped default themes are these: Themes directory on Github

You can check them out on our Demo page.

Of course you can use your own custom theme (see Custom themes).

minify

minify

| Data type: boolean | Default: 1 |

Cookieman comes with both minified and regular stylesheets and JavaScripts for the demo themes.

It set to 1, the minified versions of the .css and .js files are used. You can set it to 0 for debugging purposes.

TypoScript setup

See a full TypoScript Configuration example.

All configuration is prepended with plugin.tx_cookieman.settings.

groups

groups

| Data type: array | Default: mandatory |

Holds the group configurations. A group contains several tracking objects.

By default, it only contains the 'mandatory' group, which includes the CookieConsent settings cookie. See a full TypoScript Configuration example.

groups.<group-key>

groups.<group-key>

| Data type: array | Default: mandatory |

A single group. The group's key (name) should not contain spaces and non-ASCII characters.

It will be saved in the settings cookie and can be checked with JavaScript: hasConsented('‹group-key›')

groups.‹group-key›.preselected

groups.<group-key>.preselected

| Data type: boolean | Default: 0 (not set) |

If enabled (1), the group's consent checkbox will be already checked when the popup opens.

The default group 'mandatory' has this set to 1.

groups.‹group-key›.disabled

groups.<group-key>.disabled

| Data type: boolean | Default: 0 (not set) |

If enabled (1), the group's consent checkbox will be disabled (cannot be changed).

The default group 'mandatory' has this set to 1.

groups.‹group-key›.trackingObjects

groups.<group-key>.trackingObjects

| Data type: array with numeric indices |

Holds a list of tracking object keys (numbered).

Example:

trackingObjects {
  0 = CookieConsent
  1 = fe_typo_user
}
Copied!

groups.‹group-key›.respectDnt

groups.<group-key>.respectDnt

| Data type: boolean | Default: 0 (not set) |

If set to 1, this group respects to the "Do-not-track" setting of your browser.

groups.‹group-key›.showDntMessage

groups.<group-key>.showDntMessage

| Data type: boolean | Default: 0 (not set) |

If set to 1 and the "Do-not-track" setting of your browser is enabled, an additional message about that is shown inside the group.

trackingObjects

trackingObjects

| Data type: array |

This array holds the tracking object configurations.

The Cookieman extension already provides several preconfigured tracking objects in the folder ./Configuration/TypoScript/TrackingObjects/ (link to the Github repository).

The default group 'mandatory' only contains the tracking object CookieConsent settings cookie.

trackingObjects.‹tracking-object-key›

trackingObjects.‹tracking-object-key›

| Data type: array | Example: fe_typo_user |

A single tracking object configuration.

Example:

plugin.tx_cookieman.settings.trackingObjects {
    // 'Matomo' is the ‹tracking-object-key›:
    Matomo {
        // injected code, if consent is given:
        inject = TEXT
        inject {
            insertData = 1
            value (
                <script data-what="Matomo" src="/{path : EXT:cookieman/Resources/Public/Js/Injects/example-inject.js}?{date : U}"></script>
            )
        }

        show {
            // set cookies, if consent is given:
            _pk_id {
                duration = 13
                durationUnit = months
                type = cookie_http+html
                provider = Matomo
            }

            // etc.
        }
    }
}
Copied!

trackingObjects.‹tracking-object-key›.inject

trackingObjects.‹tracking-object-key›.inject

| Data type: data-type-html-code / data-type-cobject | Example: <script src="/path/to/tracking-code.js"></script> |

Each HTML tag in here will be appended to the page when the respective group is consented. This can be <script>, <img> or anything else.

You can either use inline script or link to an external file (useful if a HTTP header Content-Security-Policy is set).

If you need a local path from your _assets directory, let TYPO3 build it. We currently recommend using TEXT with insertData = 1 and the getText {path : EXT:…}. The preceding root path (/) is necessary for it to work on subpages. We recommend adding ?{date : U} to add a cache-busting parameter. See the example above.

It has shortcomings (namely the missing base and missing cache busting ?parameter. See https://forge.typo3.org/issues/99203#change-507069).

For v13 we can use the {asset : ...}` getText function (https://review.typo3.org/c/Packages/TYPO3.CMS/+/77018).

trackingObjects.‹tracking-object-key›.show

trackingObjects.‹tracking-object-key›.show

| Data type: array |

The actual rows of the table, each representing one "tracking item" (usually a cookie).

trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›

trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›

| Data type: array | Example: _pk_id |

A single "tracking item" (e.g. the name of a cookie). A cookie that matches this name will be removed when consent for the group in which this tracking object is included is revoked. (see also trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›.htmlCookieRemovalPattern)

trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›.duration

trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›.duration

| Data type: data-type-positive-integer | Example: 12 |

The lifetime of the tracking object (only the "number" part).

trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›.durationUnit

trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›.durationUnit

| Data type: data-type-string | Example: months |

The lifetime of the tracking object (only the "unit" part).

trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›.type

trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›.type

| Data type: data-type-string | Example: cookie_http+html |

The type of tracking.

Possible (default) keywords:

  • cookie_http+html: an HTML (=HTTP+HTML) cookie, which is also readable from JavaScript. This is the only type that can be removed after consent has been revoked.
  • cookie_http: an HTTP cookie
  • pixel: a tracking pixel

trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›.provider

trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›.provider

| Data type: data-type-string | Example: Google |

The provider of the cookie or tracking object.

trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›.htmlCookieRemovalPattern

trackingObjects.‹tracking-object-key›.show.‹tracking-item-key›.htmlCookieRemovalPattern

| Data type: data-type-string | Example: ^_gat(?:_UA-d+-d+)?$ |

You can (optionally) set a regex pattern for cookie names here. It will be used during cookie removal. If would remove all matched cookies when consent for the group in which this tracking object is included is revoked. If this is empty, the tracking object key is used for deletion (see trackingObjects.‹tracking-object-key›).

Custom themes

Target group: Developers, Integrators

Adapt an existing theme

If you want to adapt an existing theme, and not necessarily create a new one, you may want to consider adding another path to the default templates via adapting the root paths as so:

page {
  1365499 = FLUIDTEMPLATE
  1365499 {
    templateRootPaths {
      150 = EXT:my-ext/Resources/Private/cookieman/Templates/{$plugin.tx_cookieman.settings.theme}/
    }
    partialRootPaths {
      150 = EXT:my-ext/Resources/Private/cookieman/Partials/
    }
    layoutRootPaths {
      150 = EXT:my-ext/Resources/Private/cookieman/Layouts/
    }
  }
}
Copied!

This way, you also do not need to add a cookieman-theme.css and cookieman-theme.js file, which are necessary when creating a full custom theme.

Create a new theme

This is a recommendation how to set up your template structure for a custom extension.

  1. Set your base path in TypoScript constants:
plugin.tx_cookieman.settings.resourcesBasePath = EXT:your_ext/Extensions/cookieman/Resources
Copied!
  1. Choose a new theme name:
plugin.tx_cookieman.settings.theme = myTheme
Copied!
  1. Create folder EXT:your_ext/Extensions/cookieman/Resources/Private/Themes/myTheme/. Add 3 folders: Templates, Partials, Layouts.
  2. These folders will have the highest priority when looking for templates, partials or layouts now. The fallback will be EXT:cookieman/Resources/Private/*.
  3. Create folder EXT:your_ext/Extensions/cookieman/Resources/Public/Themes/myTheme. This will hold the files cookieman-theme(.min).css and cookieman-theme(.min).js. Reimplement the methods cookieman.show() and cookieman.hide() in cookieman-theme(.min).js.
  4. Copy the .css, .js and .html files as needed from a default theme.
  5. Adapt the HTML/CSS/JS as needed.

Global functionality with data-attributes

<* data-cookieman-show>

Opens the cookieman dialog

It can be added to any HTML element. The element does not have to be there on initial load (thus it should work with web components, VueJS, react, etc.).

Example:

<button data-cookieman-show>
  Adjust your cookie preferences
</button>
Copied!

How-To

Target group: Developers, Integrators

TrackingObjects

What are TrackingObjects?

A TrackingObject is an array which includes one or more tracking items (usually cookies). For example, the TrackingObject GoogleAnalytics contains five cookies which are used by this service. They are listed inside the show array.

Depending on the purpose a TrackingObject has, you need to inject HTML code after the user has given his consent (see next section).

Adding a preconfigured TrackingObject

Cookieman already provides some preconfigured TrackingObjects.

You can add selected TrackingObjects with two (or three) steps in TypoScript:

  1. Import the provided definitions.
  2. Add the key (name) of the TrackingObject.
# 1. Include provided definitions of TrackingObjects:
@import 'EXT:cookieman/Configuration/TypoScript/TrackingObjects/*.typoscript'

# 2. Add the TrackingObject key to a group:
plugin.tx_cookieman.settings.groups {
    mandatory {
        trackingObjects {
            10 = fe_typo_user
        }
    }
}
Copied!
  1. If a TrackingObject needs to inject HTML code, you'll have to add this in a third step:
# 1. Include provided definitions of TrackingObjects:
@import 'EXT:cookieman/Configuration/TypoScript/TrackingObjects/*.typoscript'

# 2. Add the TrackingObject key to a group (see below how to configure a new group):
plugin.tx_cookieman.settings.groups {
    analytics {
        trackingObjects {
            10 = GoogleAnalytics
        }
    }
}

# 3. Add the tracking code to the TrackingObject:
plugin.tx_cookieman.settings.trackingObjects {
    GoogleAnalytics {
        inject (
        <script>
            (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-XXXXX-Y', 'auto');
            ga('send', 'pageview');
        </script>
        )
    }
}
Copied!

Only add the used tracking items (cookies)

The provided TrackingObject definitions contain commonly used cookies of a service. You'll need to check it your website really uses all these cookies!

For example, Matomo will only use the _pk_hsr cookie if the Heatmap & Session recording plugin is enabled!

You can remove any default tracking item like this:

plugin.tx_cookieman.settings.trackingObjects.Matomo.show._pk_hsr >
Copied!

Adding a new custom TrackingObject

A new TrackingObject of course needs some additional configuration:

  1. Configure the new TrackingObject.
  2. Add the new TrackingObject to a group.
  3. Provide necessary localization labels which are shown in the consent popup.
plugin.tx_cookieman {
    settings {
        # 1. Configure the new TrackingObject:
        trackingObjects {
            PHPsession {
                # 1a. Configure the table row information:
                show {
                    PHPSESSID {
                        duration =
                        durationUnit = session
                        type = cookie_http+html
                        provider = Website
                        # 1b. Set a Regular Expression pattern that matches the name of the cookie,
                        #     if the cookie name or parts of it are dynamic, so the cookie can be automatically
                        #     removed in case the user revokes the consent. (optional)
                        #     Please note that you must not provide regex delimiters and can not set options
                        # htmlCookieRemovalPattern = ^regex\.\d+\.[a-fA-F0-9]+$
                    }
                }

                # 1c. Add the tracking code (optional):
                #inject (
                #    <!-- optional HTML tracking code -->
                #)
            }
        }

        # 2. Add the new TrackingObject to a group:
        groups.mandatory.trackingObjects {
            20 = PHPsession
        }
    }

    # 3. Provide necessary localization labels:
    _LOCAL_LANG {
        default {
            trackingobject.PHPSESSID.desc = This temporary cookie is set by PHP to store current session data (e.g. form data).
        }

        de {
            trackingobject.PHPSESSID.desc = Dieser temporäre Cookie wird von PHP gesetzt, um aktuelle Sitzungsdaten zu speichern (z.B. Formulardaten).
        }
    }
}
Copied!

Groups

What are Groups?

TrackingObjects can be arranged in groups that fit their purpose (technically necessary, statistics, marketing, …).

You can configure that a group is mandatory (and therefore preselected and disabled) or that the "Do-not-track" setting of your browser is respected.

Adding a new custom group

A new group needs the following configuration:

  1. Add the new group.
  2. Add the desired TrackingObjects to the group.
  3. Add settings to the group (optional).
  4. Provide necessary localization labels.
plugin.tx_cookieman {
    settings {
        groups {
            # 1. Add the new group:
            statistics {
                # 2. Add TrackingObjects to this group:
                trackingObjects {
                    10 = Matomo
                    20 = GoogleAnalytics
                }

                # 3. Optional settings: respect the 'Do Not Track' browser setting:
                respectDnt = 1
                showDntMessage = 1
            }
        }
    }

    # 4. Provide necessary localization labels:
    _LOCAL_LANG {
        default {
            group.statistics = Statistics
            group.statistics.desc = Explain the general purpose of the cookies here.
        }

        de {
            group.statistics = Statistiken
            group.statistics.desc = Beschreibe hier den allgemeinen Einsatzzweck der Cookies.
        }
    }
}
Copied!

Other topics

Content Security Policy

If your website sets the HTTP header Content-Security-Policy (without the unrecommended option 'unsafe-inline'), it will block all inline code – including your tracking codes.

In order to use tracking within such an environment, you have to move your tracking codes to external files and load them from there.

Cookieman allows to add external sources with the inject configuration:

plugin.tx_cookieman.settings.trackingObjects {
    Matomo {
        inject = TEXT
        inject {
            insertData = 1
            value (
                <script src="/{path : EXT:your_sitepackage/Resources/Public/JavaScript/matomo-trackingcode.js}?{date : U}"></script>
                <script src="https://your-matomo-server.com/path/to/matomo.js" async defer></script>
            )
        }
    }
}
Copied!

Translation

Target group: Developers, Integrators

All strings are translatable. Translations are managed on Crowdin. Click the button to help translating!

Crowdin localization status

Override translations

You can override translations by registering your .xlf-file as override in your ext_localconf.php (this example uses a configure_cookieman extension that we recommend to hold all your cookieman configuration):

$GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride']['EXT:cookieman/Resources/Private/Language/locallang.xlf'][]
    = 'EXT:configure_cookieman/Resources/Private/Language/locallang_cookieman.xlf';
Copied!

Add translations for new groups and tracking objects

If you have added groups or tracking objects, you will have to add these translation strings:

group.‹group-key›
Shown as group title.
group.‹group-key›.desc
Shown as introductory text block above the table (optional).
trackingobject.‹tracking-object-key›.desc
Shown in the table column "Purpose".
type.‹your-custom-type-key›
Shown in the table column "Type".

Contributing

Target group: Contributors

Thank you for considering contributions! You can contact us with any questions.

Documentation

You are welcome to help improve this guide. Just click on "Edit me on GitHub" on the top right to submit your improvement via a Pull Request.

Translations

Translations are managed on the official TYPO3 translation platform. See Translation.

Feedback

Any problems? You miss a feature? There is an incompatibility? You have strategic input?

Please open an issue at our Github repository after you have read the documentation.

Code (Templates, JavaScript, PHP)

We are happy to receive pull requests.

Branches

We use one branch for each stable TYPO3 API version. This model is not followed by many extensions. It allows us to focus on that API only and not worry about compatibility constructs or inabilities to incorporate any new TYPO3 feature. So absolutely no if (TYPO3_VERSION ...) in cookieman.

Also it simplifies testing, as each version might need a different setup.

After switching branches, you might need a git clean -fdX to remove any ignored files which were created by another version's build (append -e '!.idea' to exclude .idea).

Supported TYPO3 versions

  • all LTS versions: features, bugfixes, security
  • ELTS versions: security

Exceptions can be made if Pull Requests are provided.

We strive to support the latest version, too (but no promises).

Releases

Releases follow semver. Including with composer via dmind/cookieman: ^2.0 shall never break any documented feature or the input or output of any function marked with @api in the code. Be sure to shoot us an angry message if we messed up!

We usually release for all maintained TYPO3 APIs at the same time and use consecutive patch versions (e.g. 2.2.3, 2.2.4, 2.2.5), each supporting one.

Create a new release

Before creating a release you should merge the automatic Crowdin PRs until TYPO3v9 (in v10+ translations are Crowdin-only, for earlier versions we distribute them because we were not on the older "poodle" server).

The DDEV host command ddev release <version, e.g. 2.5.7> will create a release commit and an annotated Git tag. It expects that you have set up Git for signing commits (git config --get user.signingKey).

Pushing the tag with git push --tags makes the new release available for composer (packagist). It also triggers the Github Actions workflow "publish-ter" which uses the TER API via "tailor" to publish the new release to TER.

Commits

We loosely follow the commit message style of conventional commits.

Run locally

ddev start && ddev launch will install a TYPO3 with example content and cookieman. This installs helper extensions that automatically enable a certain theme and some TypoScript setup to facilitate development. The admin user is "admin", password "aaAA11!!".

The ddev custom command ddev install-git-hooks installs CGL checkers as pre-commit hooks (only tested on Linux so far - the script runs under the container environment so good chances that this would work for other OSs as well).

To throw away the database and restart cleanly, run ddev delete -Oy && git clean -fdX -e '!.idea' && ddev start

Run in Gitpod

Thanks to https://drud.github.io/ddev-gitpod-launcher/, we are able to develop on cookieman with DDEV in the cloud.

This link opens the cookieman development environment in Gitpod.

Composer scripts

Have a look at the composer.json's script section. This is the main entry point for commands needed during development.

  • ddev composer cookieman:... enables an official cookieman theme. The "customtheme" shall resemble an integrator following our documentation.
  • ddev composer build generates minified JS/CSS.
  • ddev composer test runs all important tests. You do not strictly have to run tests before opening a pull request - they are also run post-commit on Github actions.
  • ddev composer fix:cgl tries to fix linting problems.

JavaScript API

cookieman.js exposes these methods:

cookieman.showOnce()

cookieman.showOnce()

| Data type: void |

Shows the confirmation modal when consent has not been saved yet.

It is automatically called on each page from cookieman-init.js (with an aditional condition, see When is the popup shown to users?)

cookieman.show()

cookieman.show()

| Data type: void |

Shows the confirmation modal.

You can also use the attribute data-cookieman-show on any element to show the modal when clicked.

<button data-cookieman-show>
  Adjust your cookie preferences
</button>
Copied!

cookieman.hide()

cookieman.hide()

| Data type: void |

Hides the confirmation modal.

cookieman.consenteds()

cookieman.consenteds()

| Data type: array | Example: ["mandatory", "ads"] |

Returns all group keys the user has consented to.

cookieman.hasConsented(groupKey)

cookieman.hasConsented(groupKey)

| Data type: boolean |

Returns true if the user has consented to the given group (e.g. 'marketing'), else false.

cookieman.hasConsentedTrackingObject(trackingObjectKey)

cookieman.hasConsentedTrackingObject(trackingObjectKey)

| Data type: boolean |

Returns true if the user has consented to all groups that contain the given trackingObject, else false.

trackingObjectKey is the trackingObjects.‹tracking object key› from TypoScript, e.g. 'Matomo'.

cookieman.onScriptLoaded(String trackingObjectKey, int scriptId, function callback)

cookieman.onScriptLoaded(String trackingObjectKey, int scriptId, function callback)

| Data type: void |

This is a hook to do things after an external script has been loaded. This is useful if you are interacting with external scripts that are loaded by Cookieman.

  • trackingObjectKey is the trackingObjects.‹tracking object key› from TypoScript, e.g. 'Matomo'.
  • scriptId is the number of the <script> inside your trackingObjects.‹tracking object key›.inject (starting from 0 with the first).
  • callback is a function reference. It receives trackingObjectKey and scriptId (see example below). The callback is called immediately if the referred to <script> has already finished loading.

Example:

cookieman.onScriptLoaded(
    'Matomo',
    0, // first script in 'inject'
    function (trackingObjectKey, scriptId) {
        _paq.push(['trackConversion'])
    }
)
Copied!