Add cookie_policy_url field to cookie banners
Introduce a required cookie_policy_url alongside the existing
privacy_policy_url (now optional) so banners can link directly to a
dedicated cookie policy — a compliance best practice recommended by
CNIL, ICO, and the EDPB. Existing rows are seeded from their current
privacy_policy_url value.
Both {{cookie_policy_link}} and {{privacy_policy_link}} placeholders
are supported independently in banner description translations.
Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -104,7 +104,7 @@ var defaultCategoryTranslationsByLanguage = map[string]map[string]struct {
|
||||
var defaultUIStringsByLanguage = map[string]map[string]string{
|
||||
"en": {
|
||||
"banner_title": "Cookie Preferences",
|
||||
"banner_description": "We use cookies to improve your experience and analyze site traffic. {{privacy_policy_link}}",
|
||||
"banner_description": "We use cookies to improve your experience and analyze site traffic. {{cookie_policy_link}}",
|
||||
"button_accept_all": "Accept all",
|
||||
"button_reject_all": "Reject all",
|
||||
"button_customize": "Customize",
|
||||
@@ -116,12 +116,13 @@ var defaultUIStringsByLanguage = map[string]map[string]string{
|
||||
"aria_hide_details": "Hide cookie details",
|
||||
"aria_cookie_settings": "Cookie settings",
|
||||
"privacy_policy_link_text": "Privacy Policy",
|
||||
"cookie_policy_link_text": "Cookie Policy",
|
||||
"placeholder_text": "This content requires {{category}} cookies.",
|
||||
"placeholder_button": "Manage cookie preferences",
|
||||
},
|
||||
"fr": {
|
||||
"banner_title": "Préférences de cookies",
|
||||
"banner_description": "Nous utilisons des cookies pour améliorer votre expérience et analyser le trafic du site. {{privacy_policy_link}}",
|
||||
"banner_description": "Nous utilisons des cookies pour améliorer votre expérience et analyser le trafic du site. {{cookie_policy_link}}",
|
||||
"button_accept_all": "Tout accepter",
|
||||
"button_reject_all": "Tout refuser",
|
||||
"button_customize": "Personnaliser",
|
||||
@@ -133,12 +134,13 @@ var defaultUIStringsByLanguage = map[string]map[string]string{
|
||||
"aria_hide_details": "Masquer les détails des cookies",
|
||||
"aria_cookie_settings": "Paramètres des cookies",
|
||||
"privacy_policy_link_text": "Politique de confidentialité",
|
||||
"cookie_policy_link_text": "Politique relative aux cookies",
|
||||
"placeholder_text": "Ce contenu nécessite les cookies {{category}}.",
|
||||
"placeholder_button": "Gérer les préférences de cookies",
|
||||
},
|
||||
"de": {
|
||||
"banner_title": "Cookie-Einstellungen",
|
||||
"banner_description": "Wir verwenden Cookies, um Ihre Erfahrung zu verbessern und den Website-Verkehr zu analysieren. {{privacy_policy_link}}",
|
||||
"banner_description": "Wir verwenden Cookies, um Ihre Erfahrung zu verbessern und den Website-Verkehr zu analysieren. {{cookie_policy_link}}",
|
||||
"button_accept_all": "Alle akzeptieren",
|
||||
"button_reject_all": "Alle ablehnen",
|
||||
"button_customize": "Anpassen",
|
||||
@@ -150,12 +152,13 @@ var defaultUIStringsByLanguage = map[string]map[string]string{
|
||||
"aria_hide_details": "Cookie-Details ausblenden",
|
||||
"aria_cookie_settings": "Cookie-Einstellungen",
|
||||
"privacy_policy_link_text": "Datenschutzrichtlinie",
|
||||
"cookie_policy_link_text": "Cookie-Richtlinie",
|
||||
"placeholder_text": "Dieser Inhalt erfordert {{category}}-Cookies.",
|
||||
"placeholder_button": "Cookie-Einstellungen verwalten",
|
||||
},
|
||||
"es": {
|
||||
"banner_title": "Preferencias de cookies",
|
||||
"banner_description": "Utilizamos cookies para mejorar su experiencia y analizar el tráfico del sitio. {{privacy_policy_link}}",
|
||||
"banner_description": "Utilizamos cookies para mejorar su experiencia y analizar el tráfico del sitio. {{cookie_policy_link}}",
|
||||
"button_accept_all": "Aceptar todo",
|
||||
"button_reject_all": "Rechazar todo",
|
||||
"button_customize": "Personalizar",
|
||||
@@ -167,6 +170,7 @@ var defaultUIStringsByLanguage = map[string]map[string]string{
|
||||
"aria_hide_details": "Ocultar detalles de cookies",
|
||||
"aria_cookie_settings": "Configuración de cookies",
|
||||
"privacy_policy_link_text": "Política de privacidad",
|
||||
"cookie_policy_link_text": "Política de cookies",
|
||||
"placeholder_text": "Este contenido requiere cookies de {{category}}.",
|
||||
"placeholder_button": "Gestionar preferencias de cookies",
|
||||
},
|
||||
|
||||
@@ -45,7 +45,8 @@ type (
|
||||
OrganizationID gid.GID
|
||||
Name string
|
||||
Origin string
|
||||
PrivacyPolicyURL string
|
||||
PrivacyPolicyURL *string
|
||||
CookiePolicyURL string
|
||||
ConsentExpiryDays int
|
||||
ConsentMode coredata.CookieConsentMode
|
||||
}
|
||||
@@ -62,6 +63,7 @@ type (
|
||||
CookieBannerID gid.GID
|
||||
Name *string
|
||||
PrivacyPolicyURL *string
|
||||
CookiePolicyURL *string
|
||||
ConsentExpiryDays *int
|
||||
ConsentMode *coredata.CookieConsentMode
|
||||
DefaultLanguage *string
|
||||
@@ -133,7 +135,8 @@ type (
|
||||
Version int `json:"version"`
|
||||
Language string `json:"language"`
|
||||
DefaultLanguage string `json:"default_language"`
|
||||
PrivacyPolicyURL string `json:"privacy_policy_url"`
|
||||
PrivacyPolicyURL string `json:"privacy_policy_url,omitempty"`
|
||||
CookiePolicyURL string `json:"cookie_policy_url"`
|
||||
ConsentExpiryDays int `json:"consent_expiry_days"`
|
||||
ConsentMode string `json:"consent_mode"`
|
||||
ShowBranding bool `json:"show_branding"`
|
||||
@@ -162,7 +165,8 @@ func (r *CreateCookieBannerRequest) Validate() error {
|
||||
v.Check(r.OrganizationID, "organization_id", validator.Required(), validator.GID(coredata.OrganizationEntityType))
|
||||
v.Check(r.Name, "name", validator.Required(), validator.SafeTextNoNewLine(255))
|
||||
v.Check(r.Origin, "origin", validator.Required(), validator.Origin())
|
||||
v.Check(r.PrivacyPolicyURL, "privacy_policy_url", validator.Required(), validator.URL())
|
||||
v.Check(r.PrivacyPolicyURL, "privacy_policy_url", validator.URL())
|
||||
v.Check(r.CookiePolicyURL, "cookie_policy_url", validator.Required(), validator.URL())
|
||||
v.Check(r.ConsentExpiryDays, "consent_expiry_days", validator.Required(), validator.Min(1))
|
||||
v.Check(r.ConsentMode, "consent_mode", validator.Required(), validator.OneOfSlice(coredata.CookieConsentModes()))
|
||||
|
||||
@@ -175,6 +179,7 @@ func (r *UpdateCookieBannerRequest) Validate() error {
|
||||
v.Check(r.CookieBannerID, "cookie_banner_id", validator.Required(), validator.GID(coredata.CookieBannerEntityType))
|
||||
v.Check(r.Name, "name", validator.SafeTextNoNewLine(255))
|
||||
v.Check(r.PrivacyPolicyURL, "privacy_policy_url", validator.URL())
|
||||
v.Check(r.CookiePolicyURL, "cookie_policy_url", validator.URL())
|
||||
v.Check(r.ConsentExpiryDays, "consent_expiry_days", validator.Min(1))
|
||||
v.Check(r.ConsentMode, "consent_mode", validator.OneOfSlice(coredata.CookieConsentModes()))
|
||||
v.Check(r.DefaultLanguage, "default_language", validator.OneOfSlice(SupportedLanguages))
|
||||
@@ -367,6 +372,7 @@ func buildSnapshot(
|
||||
|
||||
return coredata.CookieBannerVersionSnapshot{
|
||||
PrivacyPolicyURL: banner.PrivacyPolicyURL,
|
||||
CookiePolicyURL: banner.CookiePolicyURL,
|
||||
ConsentExpiryDays: banner.ConsentExpiryDays,
|
||||
ConsentMode: string(banner.ConsentMode),
|
||||
DefaultLanguage: banner.DefaultLanguage,
|
||||
@@ -541,6 +547,7 @@ func (s *Service) CreateCookieBanner(
|
||||
Origin: CanonicalizeOrigin(req.Origin),
|
||||
State: coredata.CookieBannerStateActive,
|
||||
PrivacyPolicyURL: req.PrivacyPolicyURL,
|
||||
CookiePolicyURL: req.CookiePolicyURL,
|
||||
ConsentExpiryDays: req.ConsentExpiryDays,
|
||||
ConsentMode: req.ConsentMode,
|
||||
ShowBranding: s.showBranding,
|
||||
@@ -768,13 +775,20 @@ func (s *Service) UpdateCookieBanner(
|
||||
return fmt.Errorf("cannot load cookie banner: %w", err)
|
||||
}
|
||||
|
||||
consentChanged := req.PrivacyPolicyURL != nil || req.ConsentExpiryDays != nil || req.ConsentMode != nil || req.DefaultLanguage != nil
|
||||
consentChanged := req.PrivacyPolicyURL != nil ||
|
||||
req.CookiePolicyURL != nil ||
|
||||
req.ConsentExpiryDays != nil ||
|
||||
req.ConsentMode != nil ||
|
||||
req.DefaultLanguage != nil
|
||||
|
||||
if req.Name != nil {
|
||||
banner.Name = *req.Name
|
||||
}
|
||||
if req.PrivacyPolicyURL != nil {
|
||||
banner.PrivacyPolicyURL = *req.PrivacyPolicyURL
|
||||
banner.PrivacyPolicyURL = req.PrivacyPolicyURL
|
||||
}
|
||||
if req.CookiePolicyURL != nil {
|
||||
banner.CookiePolicyURL = *req.CookiePolicyURL
|
||||
}
|
||||
if req.ConsentExpiryDays != nil {
|
||||
banner.ConsentExpiryDays = *req.ConsentExpiryDays
|
||||
@@ -1817,12 +1831,18 @@ func buildBannerConfig(
|
||||
}
|
||||
}
|
||||
|
||||
var privacyPolicyURL string
|
||||
if snapshot.PrivacyPolicyURL != nil {
|
||||
privacyPolicyURL = *snapshot.PrivacyPolicyURL
|
||||
}
|
||||
|
||||
return &BannerConfig{
|
||||
BannerID: banner.ID,
|
||||
Version: version.Version,
|
||||
Language: resolvedLang,
|
||||
DefaultLanguage: defaultLang,
|
||||
PrivacyPolicyURL: snapshot.PrivacyPolicyURL,
|
||||
PrivacyPolicyURL: privacyPolicyURL,
|
||||
CookiePolicyURL: snapshot.CookiePolicyURL,
|
||||
ConsentExpiryDays: snapshot.ConsentExpiryDays,
|
||||
ConsentMode: snapshot.ConsentMode,
|
||||
ShowBranding: banner.ShowBranding,
|
||||
|
||||
Reference in New Issue
Block a user