Skip to content

Commit

Permalink
Update documentation about scripts and GDPR
Browse files Browse the repository at this point in the history
  • Loading branch information
dtrucs committed Oct 10, 2023
1 parent f2222e8 commit afeb76a
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 7 deletions.
146 changes: 146 additions & 0 deletions docs/customization-scripts-GDPR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Scripts and GDPR

## Executing external scripts

You can inject additional scripts into your app by creating the following files:

- `customization/html/scriptsHeader.html`: scripts injected in the `<head>` of the document.
- `customization/html/scriptsFooter.html`: scripts injected just before the `</body>` end tag.

Within each of these templates you need you can write one or more `<script>` tags.

```html
<script>
console.log("hello");
</script>
```

The above example will be executed once the page is loaded and each time the browser is hard reloaded. Due to the application's dynamic router, the script will not be executed on a **page change**.

If you need to execute the script on every page change you need to attach an event listener.

```html
<script>
window.next.router.events.on("routeChangeComplete", function (url) {
console.log(`hello ${url}`);
});
</script>
```

NB: In Geotrek Rando prior to version 3.15.4, the `window.next` object is **not yet loaded** when scripts are run. You must therefore find a strategy to wait for it before attaching the event listener.

## GDPR

### Privacy policy link

To be GDPR compliant, you must have a page describing the privacy policy.
It can be an internal or external page. And you can define its link in the `privacyPolicyLink` key in `global.json`.
Bear in mind that if this key is not defined, the consent modal will not be displayed and **no script will be executed**.

### Third-party scripts

Some scripts require the user's consent before being executed.
To control their execution, additional attributes must be added.

The script below will not be executed until the user has given his consent.
The attributes `type`, `data-type`, `data-name` are mandatory to tell the app how to handle them.
If you link to an external script you need to replace the `src` attribute by `data-src`.
More information in the [Orejime documentation](https://github.com/empreinte-digitale/orejime/#third-party-script-tags-change)).

Other attributes are optionals:

- `data-title` is the readable name dislayed to the user. If not defined, the value of `data-name` is displayed.
- `data-purposes` informs the user to which category(ies) this script belongs. "ads", "analytics", and "security" are available, you can add more by completing the translations (search `consents.modal.purposes`). NB: you can define more than one purpose by separating them with a coma (for example `data-purposes="ads,analytics"`)
- `data-cookies` String containing a comma-delimited regexp expression (without `/` delimiters) giving the names of the cookies set by the third-party script. If the user withdraws consent for a given third-party, the app will automatically delete all corresponding cookies.

```html
<script
type="opt-in"
data-type="application/javascript"
data-title="Google Tag Manager"
data-name="google-tag-manager"
data-purposes="analytics"
data-cookies="^_ga,^_gat,^_gid,^__utma,^__utmb,^__utmc,^__utmt,^__utmz"
data-src="https://www.googletagmanager.com/gtag/js?id=<GOOGLE_ANALYTICS_ID>"
></script>
```

To rely several scripts with the same consent, you need to match their `type`, `data-type`, `data-name` values, the others won't be read.

```html
<script
type="opt-in"
data-type="application/javascript"
data-name="google-tag-manager"
>
// Call the analytics Google Tag Manager tracking script
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '<GOOGLE_ANALYTICS_ID>');
</script>
```

You can now add an additional script to send each visited page to the server.

```html
<script
type="opt-in"
data-type="application/javascript"
data-name="google-tag-manager"
>
// Send visit on each dynamic page change
window.next.router.events.on('routeChangeComplete', function(url) {
window.dataLayer.push({
event: "pageview",
page: url,
})
});
</script>
```

As we saw earlier, this script should only be executed with the user's consent. But once the `routeChangeComplete` is attached, the script continues to be executed at every page change, even if the user suddenly withdraws consent.

To avoid this, one solution is to check the user's acceptance in the cookies.

```diff
<script
type="opt-in"
data-type="application/javascript"
data-name="google-tag-manager"
>
// Send visit on each dynamic page change
window.next.router.events.on('routeChangeComplete', function(url) {
+ // Check the user's acceptance of "google-tag-manager" in the cookies
+ if (JSON.parse(new URLSearchParams(document.cookie.replaceAll('; ', '&')).get('orejime') ?? null)?.["google-tag-manager"] !== true) {
+ return;
+ }
window.dataLayer.push({
event: "pageview",
page: url,
})
});
</script>
```

### Modal consent

On the user's first visit, if there are at least one `type="opt-in"` script and there is no saved cookie of the user's preferance, the consent modal is displayed.
Once the user has made his choice, it is no longer displayed.

If the user wished to modify his consent, a "Change cookie preference" button is located in the footer's app. If there is no third-party script, this button is not displayed.
It's also possible te define a button anywhere in a [custom HTML template](customization.md#html--scripts). You need to define a `button` tag with `data-trigger-consent-modal` attribute.

For example:

```html
<button
data-trigger-consent-modal
type="button"
class="flex py-2 px-4 border border-solid border-primary1 rounded-lg text-sm text-primary1 bg-white font-semibold transition transition-color hover:bg-primary2 focus:bg-primary2"
>
Change cookie preference
</button>
```

And like the button in the footer, if there is no third-party script, this button is not displayed.
17 changes: 10 additions & 7 deletions docs/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ In json files, you can just override the primary keys you need. You have to over
- `minAltitudeDifferenceToDisplayElevationProfile`: Minimum altitude difference in meters required to display the elevation profile in the current trek
- `accessibilityCodeNumber`: emergency number. Default set to `114`.
- `displayObjectsRelatedToItinerantTreks`: An object containing many booleans to display/hide objects related to itinerant treks. The keys are `POIs`,`touristicContents`,`sensitiveAreas`,`infrastructures`,`signages`,`service` and are all set to `true` by default. Indeed multi-days treks can be long and have a lot a related objects which is very long to display and not really readable. That's why you can disable some related objects that will not be displayed on itinerant main detail page, but will be displayed on steps detail pages and any other treks detail pages.
- `privacyPolicyLink`: link of the privacy policy (More information in [GDPR documentation](customization-scripts-GDPR.md#GDPR)).

- `header.json` to define logo URL, default and available languages, number items to flatpages to display in navbar (see default values in https://github.com/GeotrekCE/Geotrek-rando-v3/blob/main/frontend/config/header.json)

Expand Down Expand Up @@ -129,12 +130,12 @@ In json files, you can just override the primary keys you need. You have to over
- `shouldDisplayText`: `true` to display the text on above the asset, `false` to hide it.

- `details.json` allows you to choose whether or not to display sections for each details pages ("trek", "touristicContent", "touristicEvent", "OutdoorSite" and "OutdoorCourse"). See the default configuration at https://github.com/GeotrekCE/Geotrek-rando-v3/blob/main/frontend/config/details.json.
There are 4 properties :
There are 4 properties :

- `name`: the name of the section
- `display`: boolean to display or not this section
- `anchor`: boolean to display or not an anchor link in the menu navigation bar
- `order`: number to define the position of this section
- `name`: the name of the section
- `display`: boolean to display or not this section
- `anchor`: boolean to display or not an anchor link in the menu navigation bar
- `order`: number to define the position of this section

NB: For "report" and "reservationWidget" sections with `anchors` set to `true`, anchor links are not displayed like other elements, but by a dedicated icon.

Expand Down Expand Up @@ -277,14 +278,16 @@ You can include some HTML parts in different sections of the layout application,
These templates can be translated by using the language code as a suffix (e.g. `homeTop-en.html` will be rendered only for the English interface). The application tries to find the localized template first, otherwise it tries the non-localized template, otherwise it displays nothing.
NB: If you want to display a message common to all languages but not to a particular language (e.g. french), just create the template suffixed with its language code (e.g. `-fr.html`) and leave it empty, and voilà!

See examples in https://github.com/GeotrekCE/Geotrek-rando-v3/tree/main/frontend/customization/html.

You can also include some scripts:

- `customization/html/scriptsHeader.html`: in the `<head>` of the document
- `customization/html/scriptsFooter.html`: just before the `</body>` end tag

The scripts templates are intended for third party scripts. Unlike the HTML parts, there is not possibility of translations.
The scripts templates are intended for third party scripts. Unlike the HTML parts, there is not possibility of translations. More information on how to write them can be found in the [Scripts and GDPR documentation](customization-scripts-GDPR.md).

See examples in https://github.com/GeotrekCE/Geotrek-rando-v3/tree/main/frontend/customization/html.
## Icons

Icons are provided by Geotrek-admin API. See [icons documentation](icons.md) to know how they have to be designed.

Expand Down

0 comments on commit afeb76a

Please sign in to comment.