Objetivo
Verificar, ponta a ponta com uma propriedade GA4 real, se o recurso de
analytics da landing (#57) funciona com o Google Analytics (gtag.js), além
do Plausible/Matomo que motivaram a feature. O foco é a CSP — se os beacons do
GA chegam ao destino ou são bloqueados silenciosamente.
Como o recurso funciona hoje (levantado no código)
- Injeção:
templates/landing.html (L12-13) emite analytics-html verbatim
(|safe) no <head> da landing. Um <script> colado ali sobrevive. ✓
- CSP base (
lib.rs::content_security_policy):
script-src 'self' 'unsafe-inline' 'unsafe-eval'{extra} → o inline gtag(...)
já é permitido pelo 'unsafe-inline'. ✓
connect-src 'self'{extra} e img-src 'self' data:{extra}.
- Widening:
routes/landing.rs (L286-294) injeta a CSP da landing com
analytics-origins adicionado a script-src, connect-src e img-src
(security_headers respeita o valor setado pelo handler via or_insert).
- Sanitização (
sanitize_csp_origins/is_safe_csp_source): aceita
[scheme://][*.]host[:port][/path] — curinga de subdomínio *. é aceito
(ex.: https://*.analytics.google.com); só o * solto é rejeitado. ✓
Conclusão preliminar (a confirmar no teste real)
Tecnicamente GA4 deve funcionar, MAS só se o operador listar todos os
domínios certos em analytics-origins. O risco concreto:
- GA4 carrega o script de
https://www.googletagmanager.com (→ script-src).
- O inline
gtag('config', ...) roda ('unsafe-inline'). ✓
- Os beacons de coleta vão para
https://www.google-analytics.com /
https://*.google-analytics.com / https://*.analytics.google.com
(→ connect-src). Se o operador listar só o googletagmanager.com, os
beacons são bloqueados pela CSP e o GA falha em silêncio.
Ou seja: provavelmente não é bug de código, e sim uma lacuna de
documentação/UX (a string de origins do GA é não-óbvia e multi-domínio).
Tarefas
Arquivos relevantes
crates/ruscker-admin/templates/landing.html (L12-13)
crates/ruscker-admin/src/lib.rs (content_security_policy, sanitize_csp_origins, is_safe_csp_source)
crates/ruscker-admin/src/routes/landing.rs (L286-294 widening)
crates/ruscker-config/src/schema.rs (analytics-html, analytics-origins)
docs/YAML_SCHEMA.md (exemplo de analytics — só Plausible hoje)
Objetivo
Verificar, ponta a ponta com uma propriedade GA4 real, se o recurso de
analytics da landing (#57) funciona com o Google Analytics (gtag.js), além
do Plausible/Matomo que motivaram a feature. O foco é a CSP — se os beacons do
GA chegam ao destino ou são bloqueados silenciosamente.
Como o recurso funciona hoje (levantado no código)
templates/landing.html(L12-13) emiteanalytics-htmlverbatim(
|safe) no<head>da landing. Um<script>colado ali sobrevive. ✓lib.rs::content_security_policy):script-src 'self' 'unsafe-inline' 'unsafe-eval'{extra}→ o inlinegtag(...)já é permitido pelo
'unsafe-inline'. ✓connect-src 'self'{extra}eimg-src 'self' data:{extra}.routes/landing.rs(L286-294) injeta a CSP da landing comanalytics-originsadicionado a script-src, connect-src e img-src(
security_headersrespeita o valor setado pelo handler viaor_insert).sanitize_csp_origins/is_safe_csp_source): aceita[scheme://][*.]host[:port][/path]— curinga de subdomínio*.é aceito(ex.:
https://*.analytics.google.com); só o*solto é rejeitado. ✓Conclusão preliminar (a confirmar no teste real)
Tecnicamente GA4 deve funcionar, MAS só se o operador listar todos os
domínios certos em
analytics-origins. O risco concreto:https://www.googletagmanager.com(→script-src).gtag('config', ...)roda ('unsafe-inline'). ✓https://www.google-analytics.com/https://*.google-analytics.com/https://*.analytics.google.com(→
connect-src). Se o operador listar só o googletagmanager.com, osbeacons são bloqueados pela CSP e o GA falha em silêncio.
Ou seja: provavelmente não é bug de código, e sim uma lacuna de
documentação/UX (a string de origins do GA é não-óbvia e multi-domínio).
Tarefas
analytics-html, listar os origins e abrir a landing em um navegador;confirmar no DevTools (Network/Console) que (a) o
gtag/jscarrega,(b) não há violação de CSP, (c) o collect chega ao GA (e aparece no
Realtime do GA).
usa endpoints regionais
region1.google-analytics.com, daí o curinga).docs/YAML_SCHEMA.md(hoje o exemplo só cobre Plausible), incluindo o
analytics-originscompleto, por ex.:
analytics-origins: "https://www.googletagmanager.com https://*.google-analytics.com https://*.analytics.google.com"analytics-htmlparece um snippet GA(contém
googletagmanager.com/gtag) masanalytics-originsnão inclui umdomínio
google-analytics.com, mostrar um aviso "faltam origins de coleta".sobrevivem ao
sanitize_csp_originse caem em connect-src/script-src/img-src).Arquivos relevantes
crates/ruscker-admin/templates/landing.html(L12-13)crates/ruscker-admin/src/lib.rs(content_security_policy,sanitize_csp_origins,is_safe_csp_source)crates/ruscker-admin/src/routes/landing.rs(L286-294 widening)crates/ruscker-config/src/schema.rs(analytics-html,analytics-origins)docs/YAML_SCHEMA.md(exemplo de analytics — só Plausible hoje)