Ensuring data privacy¶
Material for MkDocs makes compliance with data privacy regulations very easy, as it offers a native cookie consent solution to seek explicit consent from users before setting up analytics. Additionally, external assets can be automatically downloaded for self-hosting.
Material for MkDocs ships a native and extensible cookie consent form which asks the user for consent prior to sending requests to third parties. Add the following to
- You can add arbitrary HTML tags in the
description, e.g. to link to your terms of service or other parts of the site.
The following properties are available:
- Google Analytics –
analytics(enabled by default)
- GitHub –
github(enabled by default)
Each cookie must receive a unique identifier which is used as a key in the
cookiesmap, and can be either set to a string, or to a map defining
If Google Analytics was configured via
- Google Analytics –
- If the
managesettings button is omitted from the
actionsproperty, the settings are always shown.
The cookie consent form includes three types of buttons:
accept– Button to accept selected cookies
reject– Button to reject all cookies
manage– Button to manage settings
- If the
When a user first visits your site, a cookie consent form is rendered:
Change cookie settings¶
In order to comply with GDPR, users must be able to change their cookie settings at any time. This can be done by adding a simple link to your copyright notice in
Built-in privacy plugin¶
The built-in privacy plugin automatically identifies external assets as part of the build process and downloads all assets for very simple self-hosting. Add the following lines to
For a list of all settings, please consult the plugin documentation.
Hosting images externally and optimizing them automatically
This option makes the built-in privacy plugin an excellent choice for when you want to host assets like images outside of your git repository in another location to keep them fresh and your repository lean.
Additionally, as of insiders-4.30.0, the built-in privacy plugin was entirely rewritten and now works perfectly with the built-in optimize plugin, which means that external assets can be passed through the same optimization pipeline as the rest of your documentation. This means you can store and edit unoptimized files outside of your repository, and let both plugins built a highly optimized site for you.
If you want to implement separate pipelines, i.e., optimize some images differently from others or exclude some images from downloading, you can use multiple instances of the built-in privacy plugin.
Why can't Material for MkDocs bundle all assets by design?
The primary reason why Material for MkDocs can't just bundle all of its own assets is the integration with Google Fonts, which offers over a thousand different fonts that can be used to render your documentation. Most of the fonts include several weights and are split up into different character sets to keep the download size small, so the browser only downloads what is really needed. For Roboto, our default regular font, this results in 42
*.woff2 files in total.
If Material for MkDocs would bundle all font files, the download size would be in the hundreds of megabytes, slowing down automated builds. Furthermore, authors might add external assets like third-party scripts or style sheets that would need to be remembered to be defined as further local assets.
This is the very reason the built-in privacy plugin exists — it automates the process of downloading all external assets manually to ensure compliance with GDPR with some some [technical limitations].
Expand to inspect example
For the official documentation, the built-in privacy plugin downloads the following resources:
. └─ assets/external/ ├─ email@example.com/dist/tablesort.min.js ├─ fonts.googleapis.com/css ├─ fonts.gstatic.com/s/ │ ├─ roboto/v29/ │ │ ├─ KFOjCnqEu92Fr1Mu51TjASc-CsTKlA.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TjASc2CsTKlA.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TjASc3CsTKlA.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TjASc5CsTKlA.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TjASc6CsQ.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TzBic-CsTKlA.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TzBic0CsTKlA.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TzBic1CsTKlA.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TzBic2CsTKlA.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TzBic3CsTKlA.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TzBic5CsTKlA.woff2 │ │ ├─ KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2 │ │ ├─ KFOkCnqEu92Fr1Mu51xEIzIFKw.woff2 │ │ ├─ KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2 │ │ ├─ KFOkCnqEu92Fr1Mu51xGIzIFKw.woff2 │ │ ├─ KFOkCnqEu92Fr1Mu51xHIzIFKw.woff2 │ │ ├─ KFOkCnqEu92Fr1Mu51xIIzI.woff2 │ │ ├─ KFOkCnqEu92Fr1Mu51xLIzIFKw.woff2 │ │ ├─ KFOkCnqEu92Fr1Mu51xMIzIFKw.woff2 │ │ ├─ KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2 │ │ ├─ KFOlCnqEu92Fr1MmSU5fBBc4.woff2 │ │ ├─ KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2 │ │ ├─ KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2 │ │ ├─ KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2 │ │ ├─ KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2 │ │ ├─ KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2 │ │ ├─ KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2 │ │ ├─ KFOlCnqEu92Fr1MmWUlfBBc4.woff2 │ │ ├─ KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2 │ │ ├─ KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2 │ │ ├─ KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2 │ │ ├─ KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2 │ │ ├─ KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2 │ │ ├─ KFOmCnqEu92Fr1Mu4WxKOzY.woff2 │ │ ├─ KFOmCnqEu92Fr1Mu4mxK.woff2 │ │ ├─ KFOmCnqEu92Fr1Mu5mxKOzY.woff2 │ │ ├─ KFOmCnqEu92Fr1Mu72xKOzY.woff2 │ │ ├─ KFOmCnqEu92Fr1Mu7GxKOzY.woff2 │ │ ├─ KFOmCnqEu92Fr1Mu7WxKOzY.woff2 │ │ └─ KFOmCnqEu92Fr1Mu7mxKOzY.woff2 │ └─ robotomono/v13/ │ ├─ L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSV0mf0h.woff2 │ ├─ L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSZ0mf0h.woff2 │ ├─ L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSd0mf0h.woff2 │ ├─ L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0mQ.woff2 │ ├─ L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSt0mf0h.woff2 │ ├─ L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSx0mf0h.woff2 │ ├─ L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtElOUlYIw.woff2 │ ├─ L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEleUlYIw.woff2 │ ├─ L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEluUlYIw.woff2 │ ├─ L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEm-Ul.woff2 │ ├─ L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEmOUlYIw.woff2 │ └─ L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEn-UlYIw.woff2 └─ polyfill.io/v3/polyfill.min.js
If you've customized the cookie consent and added a