Most websites now have a popup when you first visit them, explaining what data is processed/stored, and asking permission for the site to use cookies. I believe it is a legal requirement in the EU.
I wondered if anyone could share their methods of doing this, or comment on what is the easiest or best way to do this with Dash?
I think in general, dash apps do not use cookies. Local and Session storage is used for things that are within the regular libraries.
Where you start to get into cookies is with people logging in, etc. Typically, the cookie is how you determine if they are logged in, especially with flask-login.
I have this in my flask app:
def cookies_check():
value = request.cookies.get('cookie_consent')
return value == 'true'
@app.context_processor
def inject_template_scope():
injections = dict()
injections.update(cookies_check=cookies_check)
return injections
And then have this in the applicable template:
{% if cookies_check() %}
{# then user has already consented so no requirement for consent banner #}
{% else %}
{# show a cookie consent banner #}
<br>
<div id="cookie-consent-container" style="background: white; font-family: Comfortaa; position: absolute;">
<strong>We value your privacy</strong><br>This site uses cookies and other technologies to improve your browsing experience,
verify your session, and perform analytics. <br>Clicking “I Consent” indicates that you agree to the use of these technologies on your device.<br>
<button id="cookie-consent" type="button">I Consent</button>
</div>
<script>
$("#loginbutton").prop("disabled",true)
var fn = function () {
document.cookie = "cookie_consent=true";
document.getElementById('cookie-consent-container').hidden = true;
$("#loginbutton").prop("disabled",false)
};
document.getElementById('cookie-consent').onclick = fn;
</script>
{% endif %}
Now, as far as Terms & Conditions and EULA, we store those being accepted per user once cookies have been accepted and login verified, but we have links plainly visible on our standard site.
Now, of course, how you display this consent button and disclaimer is completely up to you. You could even use a callback that then adds the cookie to document or response from the server.
Hi, unfortunately I haven’t had time to look at this yet as something more pressing has come up, but I just wanted to thank you for sharing your code and screenshot, that is very kind I will post back here if I have queries when I get chance to look at it, thank you again!
Hey @jinnyzor, I ended up using client-side callbacks to insert the GDPR permission. I did not figure out what to do next with your suggestion. What I did was use client-side callbacks to edit the document. I don’t know if it is secure or something (I followed a tip on the documentation to add scripts through client-side callbacks).
Here is a simple code example:
import dash
from dash import dcc, html, Input, Output, State
app = dash.Dash(__name__)
# Layout of the app
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='page-content'),
dcc.Store(id='cookie-consent', storage_type='session'),
html.Div(
id='cookie-banner',
children=[
html.P("This website uses cookies to ensure you get the best experience."),
html.Button("Accept", id='accept-cookies', n_clicks=0)
],
style={'display': 'none', 'position': 'fixed', 'bottom': '10px', 'width': '100%', 'background': '#ccc', 'padding': '10px', 'textAlign': 'center'}
)
])
app.clientside_callback(
"""
function(href, n_clicks) {
let consent = document.cookie.split('; ').find(row => row.startsWith('cookie-consent='));
if (consent === undefined && n_clicks > 0) {
const d = new Date();
d.setTime(d.getTime() + (365*24*60*60*1000)); // 1 year
const expires = "expires=" + d.toUTCString();
document.cookie = "cookie-consent=true;" + expires + ";path=/";
consent = "cookie-consent=true";
}
if (consent === undefined) {
document.getElementById('cookie-banner').style.display = 'block';
} else {
document.getElementById('cookie-banner').style.display = 'none';
}
return consent !== undefined;
}
""",
Output('cookie-consent', 'data'),
Input('url', 'href'),
Input('accept-cookies', 'n_clicks')
)
# Conditionally add gtag script
app.clientside_callback(
"""
function(consent) {
if (consent) {
const scriptId = 'gtag-script';
if (!document.getElementById(scriptId)) {
const script = document.createElement('script');
script.id = scriptId;
script.src = 'https://www.googletagmanager.com/gtag/js?id=[GA_id]';
document.head.appendChild(script);
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', [GA_id]);
}
}
return '';
}
""",
Output('page-content', 'children'),
Input('cookie-consent', 'data')
)
if __name__ == '__main__':
app.run_server(debug=True)
Sure you can do that. There really wasn’t a need to do anything else as the consent needs to be done each time upon each session. So the cookie will be there.