Skip to content

Commit

Permalink
✨feat: support privacy-respecting analytics
Browse files Browse the repository at this point in the history
  • Loading branch information
welpo committed Sep 28, 2023
1 parent 342a62c commit e4f70b6
Show file tree
Hide file tree
Showing 11 changed files with 282 additions and 74 deletions.
19 changes: 19 additions & 0 deletions config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,25 @@ allowed_domains = [
# Please see https://welpo.github.io/tabi/blog/custom-font-subset/ to learn how to create this file.
custom_subset = true

[extra.analytics]
# Specify which analytics service you want to use.
# Supported options: ["goatcounter", "umami", "plausible"]
# service = "umami"

# Unique identifier for tracking.
# For GoatCounter, this is the code you choose during signup.
# For Umami, this is the website ID.
# For Plausible, this is the domain name (e.g. "example.com").
# Note: Leave this field empty if you're self-hosting.
# id = "yourID"

# Optional: Specify the URL for self-hosted analytics instances.
# For GoatCounter: Base URL like "https://stats.example.com"
# For Umami: Base URL like "https://umami.example.com"
# For Plausible: Base URL like "https://plausible.example.com"
# Leave this field empty if you're using the service's default hosting.
# self_hosted_url = ""

# giscus support for comments. https://giscus.app
# Setup instructions: https://welpo.github.io/tabi/blog/comments/#setup
[extra.giscus]
Expand Down
36 changes: 33 additions & 3 deletions content/blog/mastering-tabi-settings.ca.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
+++
title = "Domina la configuració de tabi: guia completa"
date = 2023-09-18
updated = 2023-09-29
description = "Descobreix les múltiples maneres en què pots personalitzar tabi."

[taxonomies]
Expand Down Expand Up @@ -443,9 +444,7 @@ Per obtenir més informació, incloent instruccions sobre com crear un subconjun

Per defecte, el feed Atom només conté el resum o descripció de les teves publicacions. Pots incloure el contingut complet de les publicacions establint `full_content_in_feed = true` a `config.toml`.

---

## Comentaris {#afegir-comentaris}
### Comentaris {#afegir-comentaris}

| Pàgina | Secció | `config.toml` | Segueix la jerarquia | Requereix JavaScript |
|:------:|:-------:|:-------------:|:-------------------:|:-------------------:|
Expand All @@ -457,6 +456,37 @@ Si vols activar els comentaris de forma global, pots fer-ho establint `enabled_f

Llegeix la [documentació](/ca/blog/comments/) per a més informació sobre els sistemes disponibles i la seva configuració.

### Anàlisi web

| Pàgina | Secció | `config.toml` | Segueix Jerarquia | Requereix JavaScript |
|:------:|:-------:|:-------------:|:-----------------:|:--------------------:|
||||||

tabi ofereix suport per a 3 sistemes d'anàlisi web que respecten la privacitat: [Plausible](https://plausible.io/), [GoatCounter](https://www.goatcounter.com/) i [Umami](https://umami.is/).

Pots configurar-los en la secció `[extra.analytics]` del teu arxiu `config.toml`.

- `service`: el servei a utilitzar. Les opcions disponibles són `"goatcounter"`, `"umami", i "plausible"`.

- `id`: l'identificador únic per al teu servei d'anàlisi. Això varia segons el servei:
- Per a GoatCounter, és el codi triat durant el registre. Instàncies auto-allotjades no requereixen aquest camp.
- Per a Umami, és l'ID del lloc web.
- Per a Plausible, és el nom de domini.

- `self_hosted_url`: Opcional. Utilitza aquest camp per especificar l'URL si tens una instància auto-allotjada. L'URL base variarà segons la teva configuració particular. Alguns exemples:
- Per a GoatCounter: `"https://stats.example.com"`
- Per a Umami: `"https://umami.example.com"`
- Per a Plausible: `"https://plausible.example.com"`

Un exemple de configuració per a GoatCounter no auto-allotjada seria:

```toml
[extra.analytics]
service = "goatcounter"
id = "tabi"
self_hosted_url = ""


---

## Icones al peu de pàgina
Expand Down
36 changes: 33 additions & 3 deletions content/blog/mastering-tabi-settings.es.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
+++
title = "Domina la configuración de tabi: guía completa"
date = 2023-09-18
updated = 2023-09-29
description = "Descubre las múltiples maneras en que puedes personalizar tabi."

[taxonomies]
Expand Down Expand Up @@ -441,9 +442,7 @@ Para obtener más información, incluyendo instrucciones sobre cómo crear un su

Por defecto, el feed Atom solo contiene el resumen/descripción de tus publicaciones. Puedes incluir el contenido completo de las publicaciones estableciendo `full_content_in_feed = true` en `config.toml`.

---

## Comentarios {#añadir-comentarios}
### Comentarios {#añadir-comentarios}

| Página | Sección | `config.toml` | Sigue la jerarquía | Requiere JavaScript |
|:------:|:-------:|:-------------:|:---------------:|:-------------------:|
Expand All @@ -455,6 +454,37 @@ Si quieres activar los comentarios de forma global, puedes hacerlo estableciendo

Lee la [documentación](/es/blog/comments/) para obtener más información sobre los sistemas disponibles y su configuración.

### Análisis web

| Página | Sección | `config.toml` | Sigue Jerarquía | Requiere JavaScript |
|:------:|:--------:|:-------------:|:----------------:|:-------------------:|
||||||

tabi ofrece soporte para 3 sistemas de análisis web que respetan la privacidad: [Plausible](https://plausible.io/), [GoatCounter](https://www.goatcounter.com/) y [Umami](https://umami.is/).

Puedes configurarlos en la sección `[extra.analytics]` de tu archivo `config.toml`.

- `service`: el servicio a utilizar. Las opciones disponibles son `"goatcounter"`, `"umami"`, y `"plausible"`.

- `id`: el identificador único para tu servicio de análisis. Esto varía según el servicio:
- Para GoatCounter, es el código elegido durante el registro. Instancias auto-alojadas no requieren este campo.
- Para Umami, es la ID del sitio web.
- Para Plausible, es el nombre de dominio.

- `self_hosted_url`. Opcional. Utiliza este campo para especificar la URL si tienes una instancia auto-alojada. La URL base variará según tu configuración particular. Algunos ejemplos:
- Para GoatCounter: `"https://stats.example.com"`
- Para Umami: `"https://umami.example.com"`
- Para Plausible: `"https://plausible.example.com"`

Un ejemplo de configuración para GoatCounter no auto-alojada sería:

```toml
[extra.analytics]
service = "goatcounter"
id = "tabi"
self_hosted_url = ""
```

---

## Iconos en el pie de página
Expand Down
36 changes: 33 additions & 3 deletions content/blog/mastering-tabi-settings.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
+++
title = "Mastering tabi Settings: A Comprehensive Guide"
date = 2023-09-18
updated = 2023-09-29
description = "Discover the many ways you can customise your tabi site."

[taxonomies]
Expand Down Expand Up @@ -445,9 +446,7 @@ For more information, including instructions on how to create a custom subset, s

By default, the Atom feed only contains the summary/description of your posts. You can include the entire posts' content by setting `full_content_in_feed = true` in `config.toml`.

---

## Comments {#adding-comments}
### Comments {#adding-comments}

| Page | Section | `config.toml` | Follows Hierarchy | Requires JavaScript |
|:----:|:-------:|:-------------:|:-----------------:|:-------------------:|
Expand All @@ -459,6 +458,37 @@ To enable a system globally (on all pages), set `enabled_for_all_posts = true` i

Read [the docs](/blog/comments/) for more information on the available systems and their setup.

### Analytics

| Page | Section | `config.toml` | Follows Hierarchy | Requires JavaScript |
|:----:|:-------:|:-------------:|:-----------------:|:-------------------:|
||||||

tabi supports 3 privacy-friendly analytics systems: [Plausible](https://plausible.io/), [GoatCounter](https://www.goatcounter.com/) and [Umami](https://umami.is/).

You can set them up in the `[extra.analytics]` section of your `config.toml`.

- `service`: Specifies which analytics service to use. Supported options are `"goatcounter"`, `"umami"`, and `"plausible"`.

- `id`: The unique identifier for your analytics service. This varies based on the service:
- For GoatCounter, it's the code chosen during signup. Self-hosted instances don't require this field.
- For Umami, it's the website ID.
- For Plausible, it's the domain name.

- `self_hosted_url`: Optional. Use this field to specify the URL for self-hosted instances of your chosen analytics service. The base URL differs based on your specific setup. Some examples:
- For GoatCounter: `"https://stats.example.com"`
- For Umami: `"https://umami.example.com"`
- For Plausible: `"https://plausible.example.com"`

An example configuration for non-self-hosted GoatCounter would look like this:

```toml
[extra.analytics]
service = "goatcounter"
id = "tabi"
self_hosted_url = ""
```

---

## Footer Icons
Expand Down
4 changes: 2 additions & 2 deletions content/blog/security.ca.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
+++
title = "Seguretat per defecte"
date = 2023-02-22
updated = 2023-07-17
updated = 2023-09-29
description = "tabi té una Política de Seguretat de Contingut (CSP) fàcilment personalitzable amb valors segurs per defecte. Obtingues tranquil·litat i un A+ en l'Observatori de Mozilla."

[taxonomies]
Expand Down Expand Up @@ -30,6 +30,6 @@ La llista `allowed_domains` especifica les URLs a les quals el lloc web hauria d

Aquesta funcionalitat permet personalitzar fàcilment les capçaleres de seguretat del lloc web per permetre casos d'ús específics, com ara inserir vídeos de YouTube, carregar scripts o tipografies remotes ([no recomanat](https://www.albertovarela.net/blog/2022/11/stop-using-google-fonts/)).

**Nota**: [habilitar els comentaris](@/blog/comments.ca.md) permet automàticament scripts i frames del sistema de comentaris corresponent, així com estils en línia no segurs en el cas de utterances i Hyvor Talk.
**Nota**: [habilitar els comentaris](@/blog/comments.ca.md) o [les analítiques](@/blog/mastering-tabi-settings.ca.md#analitiques) automàticament permet scripts/frames/estils/connexions en funció del servei habilitat.

[^1]: Requereix una configuració adequada del servidor web (p. ex., redirigir el trànsit HTTP a HTTPS).
4 changes: 2 additions & 2 deletions content/blog/security.es.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
+++
title = "Seguro por defecto"
date = 2023-02-22
updated = 2023-07-17
updated = 2023-09-29
description = "tabi tiene una Política de Seguridad de Contenido (CSP) fácilmente personalizable con configuraciones seguras. Obtén tranquilidad y una calificación de A+ en Mozilla Observatory."

[taxonomies]
Expand Down Expand Up @@ -30,6 +30,6 @@ La lista `allowed_domains` especifica las URL a las que el sitio web debería po

Esta función permite personalizar fácilmente las cabeceras de seguridad del sitio web para permitir casos de uso específicos, como la incrustación de videos de YouTube, la carga de scripts o fuentes remotas ([no recomendado](https://www.albertovarela.net/blog/2022/11/stop-using-google-fonts/)).

**Nota**: [habilitar los comentarios](@/blog/comments.es.md) permite automáticamente scripts y frames del sistema de comentarios correspondiente, así como estilos unsafe-inline en el caso de utterances o Hyvor Talk.
**Nota**: [habilitar los comentarios](@/blog/comments.es.md) o [las analíticas](@/blog/mastering-tabi-settings.es.md#analisis-web) automáticamente permite scripts/frames/estilos/conexiones en función del servicio habilitado.

[^1]: Requiere una configuración adecuada del servidor web (por ejemplo, redirigir el tráfico HTTP a HTTPS).
4 changes: 2 additions & 2 deletions content/blog/security.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
+++
title = "Secure by default"
date = 2023-02-22
updated = 2023-07-17
updated = 2023-09-29
description = "tabi has an easily customizable Content Security Policy (CSP) with safe defaults. Get peace of mind and an A+ on Mozilla Observatory."

[taxonomies]
Expand Down Expand Up @@ -30,6 +30,6 @@ The `allowed_domains` list specifies the URLs that the website should be able to

This feature allows you to easily customize the website's security headers to allow for specific use cases, such as embedding YouTube videos, loading scripts or remote fonts ([not recommended](https://www.albertovarela.net/blog/2022/11/stop-using-google-fonts/)).

**Note**: [enabling comments](@/blog/comments.md) automatically allows scripts and frames from the comment system, as well as unsafe-inline styles when using utterances or Hyvor Talk.
**Note**: [enabling comments](@/blog/comments.md) or [analytics](@/blog/mastering-tabi-settings.md#analytics) automatically allows scripts/frames/styles/connections as needed from the respective services.

[^1]: Requires proper webserver configuration (e.g. redirecting HTTP traffic to HTTPS).
41 changes: 41 additions & 0 deletions templates/partials/analytics.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{% set analytics_service = config.extra.analytics.service %}
{% set analytics_id = config.extra.analytics.id | default(value="") %}
{% set self_hosted_url = config.extra.analytics.self_hosted_url | default(value="") %}

{% if analytics_service == "goatcounter" %}
{% if self_hosted_url %}
<script
data-goatcounter="{{ self_hosted_url ~ '/count' }}"
async
src="{{ self_hosted_url ~ '/count.js' }}">
</script>
{% else %}
<script
data-goatcounter="https://{{ analytics_id }}.goatcounter.com/count"
async
src="//gc.zgo.at/count.js">
</script>
{% endif %}

{% elif analytics_service == "umami" %}
{% if self_hosted_url %}
<script
async defer
data-website-id="{{ analytics_id }}"
src="{{ self_hosted_url ~ '/umami.js' }}">
</script>
{% else %}
<script
async defer
data-website-id="{{ analytics_id }}"
src="https://analytics.eu.umami.is/script.js">
</script>
{% endif %}

{% elif analytics_service == "plausible" %}
<script
defer
data-domain="{{ analytics_id }}"
src="{% if self_hosted_url %}{{ self_hosted_url ~ '/js/plausible.js' }}{% else %}https://plausible.io/js/script.js{% endif %}"
></script>
{% endif %}
93 changes: 93 additions & 0 deletions templates/partials/content_security_policy.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'
{%- if config.extra.allowed_domains -%}
;
{#- Check if a comment system is enabled to allow the necessary domains and directives -#}
{%- set utterances_enabled = config.extra.utterances.enabled_for_all_posts or page.extra.utterances -%}
{%- set giscus_enabled = config.extra.giscus.enabled_for_all_posts or page.extra.giscus -%}
{%- set hyvortalk_enabled = config.extra.hyvortalk.enabled_for_all_posts or page.extra.hyvortalk -%}
{%- set isso_enabled = config.extra.isso.enabled_for_all_posts or page.extra.isso -%}
{#- Initialise a base script-src directive -#}
{%- set script_src = "script-src 'self'" -%}

{#- Initialise a base connect-src directive -#}
{%- set connect_src = "connect-src 'self'" -%}

{# Base logic for appending analytics domains #}
{%- set analytics_url = config.extra.analytics.self_hosted_url | default(value="") %}
{%- if analytics_url -%}
{%- set script_src = script_src ~ " " ~ analytics_url -%}
{%- set connect_src = connect_src ~ " " ~ analytics_url -%}
{%- else -%}
{%- if config.extra.analytics.service -%}
{%- if config.extra.analytics.service == "goatcounter" -%}
{%- set script_src = script_src ~ " gc.zgo.at" -%}
{%- set connect_src = connect_src ~ " gc.zgo.at" -%}
{%- elif config.extra.analytics.service == "umami" -%}
{%- set script_src = script_src ~ " analytics.eu.umami.is" -%}
{%- set connect_src = connect_src ~ " analytics.eu.umami.is" -%}
{%- elif config.extra.analytics.service == "plausible" -%}
{%- set script_src = script_src ~ " plausible.io" -%}
{%- set connect_src = connect_src ~ " plausible.io" -%}
{%- endif -%}
{%- endif -%}
{%- endif -%}

{%- if hyvortalk_enabled -%}
{%- set connect_src = connect_src ~ " talk.hyvor.com" -%}
{%- set script_src = script_src ~ " talk.hyvor.com" -%}
{%- elif isso_enabled -%}
{%- set connect_src = connect_src ~ " " ~ config.extra.isso.endpoint_url -%}
{%- set script_src = script_src ~ " " ~ config.extra.isso.endpoint_url -%}
{%- elif giscus_enabled -%}
{%- set script_src = script_src ~ " " ~ " giscus.app" -%}
{%- elif utterances_enabled -%}
{%- set script_src = script_src ~ " " ~ " utteranc.es" -%}
{%- endif -%}

{#- Append WebSocket for Zola serve mode -#}
{%- if config.mode == "serve" -%}
{%- set connect_src = connect_src ~ " ws:" -%}
{%- endif -%}

{%- for domain in config.extra.allowed_domains -%}
{%- if domain.directive == "connect-src" -%}
{%- set configured_connect_src = domain.domains | join(sep=' ') -%}
{%- set_global connect_src = connect_src ~ " " ~ configured_connect_src -%}
{%- continue -%}
{%- endif -%}

{%- if domain.directive == "script-src" -%}
{%- set configured_script_src = domain.domains | join(sep=' ') -%}
{%- set_global script_src = script_src ~ " " ~ configured_script_src -%}
{%- continue -%}
{%- endif -%}

{#- Handle directives that are not connect-src -#}
{{ domain.directive }} {{ domain.domains | join(sep=' ') -}}

{%- if utterances_enabled or hyvortalk_enabled -%}
{%- if domain.directive == "style-src" %} 'unsafe-inline'
{%- endif -%}
{%- endif -%}

{%- if domain.directive == "frame-src" -%}
{%- if giscus_enabled %} giscus.app
{%- elif utterances_enabled %} utteranc.es
{%- elif hyvortalk_enabled %} talk.hyvor.com
{%- endif %}
{%- endif -%}

{%- if not loop.last -%}
;
{%- endif -%}
{%- endfor -%}

{#- Insert the generated connect-src -#}
{{ ";" ~ connect_src }}

{#- Insert the generated script-src -#}
{{ ";" ~ script_src }}

{%- endif -%}">
Loading

0 comments on commit e4f70b6

Please sign in to comment.