chameleon-system-private/tracking-consent-bundle

Provides a consent overlay for tracking, includes option to change tracking choice later and choice logging.

8.47.1 2025-12-15 13:55 UTC

README

Tracking Consent Bundle will show the user a consent form. The consent can be logged if logging is activated. Log entries will be removed when they are older than one year (configurable via the portal consent configuration).

Consent can be changed using the module Tracking Consent: View/Change Configuration (service chameleon_system_tracking_consent.tracking_consent_module).

The consent, including the tracking categories for which consent will be asked, can be configured for each portal on the tab Tracking Consent.

You can check the current users consent using the service chameleon_system_tracking_consent.consent_service (\ChameleonSystem\TrackingConsent\Interfaces\ConsentServiceInterface).

Installation

  • Add \ChameleonSystem\TrackingConsentBundle\ChameleonSystemTrackingConsentBundle to your AppKernel
  • add the following to your routing.yml
    chameleon_system_tracking_consent:
      resource: "@ChameleonSystemTrackingConsentBundle/Resources/config/routing.yml"
      type:     yaml
    
  • Create a system page with system name "privacy-policy" (see iFrames below)

Consent and Page reload

When the user submits the consent choice, the page will reload. If your webpage handles the users landingpage differently then other pages (by, for example, showing a popup on the first page visited), then you may want to modify your page in suche a way, that the landing page handling only occurs once the user has submitted the consent choice.

Track landing page information

Since tracking will only start once the user consents to it, we need to track the landing page data until consent is given. If the user does this on a sub-page instead of directly on the landing page, then all data about the source of the user will be lost.

To mitigate this problem, this bundle stores alle data of the landing page in the users' session.

You can access the data using the service chameleon_system_tracking_consent.landing_page_referrer_data_service

Using the Data

When using the data, you should do the following a) Once you have gotten consent from the user, read the data and send it to google:

  • set the location to the landing page campaignUrl
  • set the page to the current URL (via js you can use document.location.pathname + document.location.search)
  • set the referrer to the landing page referrerUrl

b) to avoid sending the data on every request once you have consent, you need to also keep track of the fact, that you sent the data. You can do this by setting a cookie and then checking for that cookie before sending the data, or by setting a flag in the session which you can then check before sending the data.

Using the Data via Tag Manager

To use the data via tag manager, you need to do the following

  1. push the landing page data to the data layer as variable landingPageData:

    {#@var trackerState \TPkgExternalTrackerState #}
    {#@var landingPageData null|\ChameleonSystem\TrackingConsent\DataModel\LandingPageReferrerDataModel #}
    {% set landingPageData = trackerState.GetStateData('chameleon_system_tracking_consent.landing_page_data') %}
    {% extends "@ChameleonSystemGoogleTagManagerShop/snippets/tagManager/tagManagerHeaderJs.html.twig" %}
    
     {% block additionalDataLayer %}
         {{ constant('\\ChameleonSystem\\GoogleTagManagerBundle\\Bridge\\Chameleon\\Constants::EVENT_PLACEHOLDER') | raw }}
    
         dataLayer.push({
             'activeUserHash': '{{ userHash |json_encode|raw  }}',
             {% if landingPageData %}
             'landingPageData': '{{ landingPageData | json_encode|raw }}',
             {% endif %}
         });
         {{ parent() }}
     {% endblock %}
    
  2. Create the data layer variable landingPageData to make the landing page data available in google tag manager.
  3. Create a first party cookie esono-consent-tracking variable to read the 'data has been sent' state.
  4. Create a javascript variable customTask - set location and referrer with the following content:

    function() {
     return function(customModel) {
         var landingPageDataSend = {{esono-consent-tracking}};
         if (1 === landingPageDataSend || '1' === landingPageDataSend) {
             return;
         }
         var landingPageData = {{landingPageData}};
         if(typeof landingPageData === 'undefined') {
           return;
         }
         var landingPageData = JSON.parse(landingPageData);
         if (null !== landingPageData.campaignUrl) {
             customModel.set('location', landingPageData.campaignUrl);
             customModel.set('page', document.location.pathname + document.location.search);
         } 
    
         if (null !== landingPageData.referrerUrl) {
             customModel.set('referrer', landingPageData.referrerUrl);
         }
         document.cookie = 'twConsent=1; SameSite=None; Secure; expires; path=/; domain=' +location.hostname;
     }
    }
    
5. Connect `customTask - set location and referrer` to your google analytics settings by adding a new Field
`customTask` with value `{{customTask - set location and referrer}}` under 'More Settings'.

Design/Layout Customization
---------------------------
The consent form can be easily configured by either providing a new layout or by overwriting an existing layout. 
The Layout file for the overlay can be set in the portal configuration. 

iFrame Embed Consent in WYSIWYG Fields
--------------------------------------

Because any external domain call could possibly include tracking data and for general privacy issues any iFrame which is
embedded in a WYSIWYG HTML field should be added to the consent manager.

At the moment only Youtube Player iFrames will be checked for consent.

If you want to add consent checks for additional external services like issue PDFs or Google Maps you will need to add an extension to 
`TextFieldWysiwygConsent.php`

The standard warning text if a Youtube video is encountered is `chameleon_system_tracking_consent.youtube_message`.
It links to the system page with system name "privacy-policy".

Open Issues
-----------

* We need to check the performance of the DOMDocument parser. Maybe it is better to use symfonys DOM Crawler
<https://symfony.com/doc/current/components/dom_crawler.html>.
* If the parser fails to load the document for any reason (invalid HTML) no content will be filtered which may lead to 
privacy issues.
* We should add more services to the list of replaced iFrames. For performance reasons it should be possible to 
enable services or if we have a list of cookies/services per group later on in the database, we could go through this
list (only active ones) and search for any of these services instead of all supported services.