<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Hitkeep – Serverküche</title><link>https://serverkueche.de/tags/hitkeep/</link><description>Hitkeep – Neueste Beiträge von Serverküche</description><generator>Hugo</generator><language>de-DE</language><managingEditor>feedback@serverkueche.de (Serverküche)</managingEditor><webMaster>feedback@serverkueche.de (Serverküche)</webMaster><copyright>2026 Serverküche</copyright><lastBuildDate>Fri, 31 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://serverkueche.de/tags/hitkeep/index.xml" rel="self" type="application/rss+xml"/><item><title>HitKeep: datenschutzfreundliche Web-Analytics selbst hosten</title><link>https://serverkueche.de/tutorials/hitkeep-analytics-selbst-hosten/</link><pubDate>Fri, 31 Jul 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/tutorials/hitkeep-analytics-selbst-hosten/</guid><description>HitKeep mit Docker und Traefik aufsetzen: cookielose, DSGVO-freundliche Website-Statistik auf dem eigenen Server – mit Tracking-Code und Backups.</description><content:encoded><![CDATA[<p>Google Analytics kennt jeder – und genau das ist das Problem: Es schickt die Daten deiner
Besucher zu Google, verlangt einen Cookie-Banner und macht dich erklärungspflichtig. HitKeep
dreht das um: cookielose Statistik auf <strong>deinem</strong> Server, unter <strong>deiner</strong> Domain, ohne dass
je ein Byte an Dritte geht.</p>
<h2 id="was-bauen-wir">Was bauen wir?</h2>
<p>Am Ende läuft <strong>HitKeep 2.12.0</strong> als einzelner Container hinter deinem Traefik, erreichbar
unter <code>https://DEINE_DOMAIN</code>. Du bekommst ein Dashboard mit Seitenaufrufen, Besuchern,
Verweildauer, Referrern und Geräten – gespeist von einem winzigen JavaScript-Snippet, das du
in deine Website einbaust. HitKeep arbeitet <strong>cookielos</strong> (kein Consent-Banner nötig) und
speichert alles lokal in einer eingebetteten DuckDB-Datenbank. Das Image ist ein schlankes
Distroless-Image (rund 71 MB), das komplett ohne externe Datenbank auskommt – ideal für einen
kleinen VPS.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>Hinweis
  </p>
  <div class="prose-kitchen text-sm">HitKeep ist „cookielos&quot;, weil es Besucher über einen täglich wechselnden Hash statt über einen
gesetzten Cookie wiedererkennt. Das ist deutlich datenschutzfreundlicher als klassisches
Tracking, ersetzt aber <strong>keine</strong> rechtliche Beratung. Ob du komplett ohne Einwilligung
auskommst, hängt von deinem konkreten Einsatz ab – im Zweifel mit einem Datenschutzbeauftragten
klären.</div>
</div>
<h2 id="voraussetzungen">Voraussetzungen</h2>
<ul>
<li>Ein Server mit <strong>Debian 13</strong> und laufendem Docker (getestet auf einem netcup VPS).</li>
<li>Ein <strong><a href="/tutorials/reverse-proxy-traefik/">Reverse Proxy mit Traefik</a></strong>, der TLS-Zertifikate
per Let&rsquo;s Encrypt holt. HitKeep bringt keinen eigenen HTTPS-Server mit – Traefik übernimmt
die Verschlüsselung. Dieses Tutorial setzt das dort beschriebene <code>proxy</code>-Netz und den
Resolver <code>le</code> voraus.</li>
<li>Eine <strong>(Sub-)Domain</strong>, die auf deinen Server zeigt (A-/AAAA-Record). Wir nutzen im Beispiel
<code>DEINE_DOMAIN</code>.</li>
<li>Die Website, die du messen willst – HitKeep misst jede Seite, in die du das Snippet einbaust.</li>
</ul>
<div class="not-prose my-6 overflow-hidden rounded-xl border border-paprika-200 bg-paprika-50 dark:border-paprika-800 dark:bg-paprika-900/20"
     data-track-content data-content-name="Affiliate-Box · /tutorials/hitkeep-analytics-selbst-hosten/" data-content-piece="VPS 1000 G12">
  <div class="flex items-center justify-between border-b border-paprika-200 bg-paprika-100 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-paprika-700 dark:border-paprika-800 dark:bg-paprika-900/40 dark:text-paprika-300">
    <span>🍳 Empfehlung</span>
    <span title="Mit * markierte Links sind Affiliate-Links.">Anzeige</span>
  </div>
  <div class="flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between">
    <div>
      <p class="text-lg font-bold text-slate-900 dark:text-white">VPS 1000 G12</p>
      <p class="mt-1 text-sm text-slate-600 dark:text-slate-300">4 vCore · 8 GB RAM · 256 GB NVMe</p>
      <p class="mt-1 text-sm font-semibold text-paprika-700 dark:text-paprika-400">ab 10,36 €/Monat</p>
      <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">Ein einzelner Container mit eingebetteter DuckDB – der kleinste vServer reicht dafür locker.</p>
    </div>
    <a href="https://www.netcup.com/de/server/vps/vps-1000-g12-12m?ref=44083" rel="sponsored noopener" target="_blank"
   data-track-event="Affiliate|netcup: Affiliate-Box|VPS 1000 G12 · {page}"
   class="inline-flex shrink-0 items-center justify-center rounded-lg bg-paprika-600 px-5 py-2.5 font-semibold text-white transition-colors hover:bg-paprika-700">
  Zu netcup →
</a>

  </div><div class="px-4 pb-4"><p class="not-prose my-3 flex flex-wrap items-center gap-x-2 gap-y-1 rounded-lg border border-herb-500/40 bg-herb-50 px-3 py-2 text-sm text-slate-700 dark:bg-herb-900/20 dark:text-slate-200">
  <span>💶 <strong>5 € Gutschein</strong> für netcup-Neukunden:</span><code data-track-voucher="36nc17844976032"
        class="rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 dark:bg-slate-800 dark:text-herb-400">36nc17844976032</code>
  <span class="text-xs text-slate-500 dark:text-slate-400">(nur Neukunden, keine Domains)</span>
</p></div>
</div>

<h2 id="schritt-für-schritt">Schritt für Schritt</h2>
<h3 id="schritt-1-jwt-secret-erzeugen">Schritt 1: JWT-Secret erzeugen</h3>
<p>HitKeep signiert die Login-Sitzungen mit einem geheimen Schlüssel. Erzeuge dir einen zufälligen
32-Byte-Wert – <strong>nicht</strong> ausdenken, sondern generieren:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">openssl rand -hex <span class="m">32</span></span></span></code></pre></div>
</div>
<p>Du bekommst eine 64 Zeichen lange Hex-Zeichenkette. Kopiere sie – sie kommt gleich in die
Konfiguration. Ändert sich dieses Secret später, werden alle offenen Logins ungültig; halte es
also stabil und geheim.</p>
<h3 id="schritt-2-compose-datei-anlegen">Schritt 2: Compose-Datei anlegen</h3>
<p>Lege einen Ordner für den Stack an und wechsle hinein:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">mkdir -p /opt/hitkeep <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /opt/hitkeep</span></span></code></pre></div>
</div>
<p>Erstelle die Datei <code>compose.yaml</code>. Ersetze <code>DEINE_DOMAIN</code> durch deine echte Domain und
<code>DEIN_JWT_SECRET</code> durch den Wert aus Schritt 1:</p>
<div class="sk-code">
  <span class="sk-code-head">YAML</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">hitkeep</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">pascalebeier/hitkeep:2.12.0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">hitkeep</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l">unless-stopped</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">HITKEEP_PUBLIC_URL</span><span class="p">:</span><span class="w"> </span><span class="l">https://DEINE_DOMAIN</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">HITKEEP_JWT_SECRET</span><span class="p">:</span><span class="w"> </span><span class="l">DEIN_JWT_SECRET</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">HITKEEP_TRUSTED_PROXIES</span><span class="p">:</span><span class="w"> </span><span class="m">172.16.0.0</span><span class="l">/12</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">HITKEEP_DB_PATH</span><span class="p">:</span><span class="w"> </span><span class="l">/var/lib/hitkeep/data/hitkeep.db</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">HITKEEP_DATA_PATH</span><span class="p">:</span><span class="w"> </span><span class="l">/var/lib/hitkeep/data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">HITKEEP_ARCHIVE_PATH</span><span class="p">:</span><span class="w"> </span><span class="l">/var/lib/hitkeep/archive</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">HITKEEP_BACKUP_PATH</span><span class="p">:</span><span class="w"> </span><span class="l">/var/lib/hitkeep/backups</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">hitkeep_data:/var/lib/hitkeep/data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">hitkeep_archive:/var/lib/hitkeep/archive</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">hitkeep_backups:/var/lib/hitkeep/backups</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.enable=true&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.hitkeep.rule=Host(`DEINE_DOMAIN`)&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.hitkeep.entrypoints=websecure&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.hitkeep.tls.certresolver=le&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.services.hitkeep.loadbalancer.server.port=8080&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">networks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">proxy]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">hitkeep_data</span><span class="p">:</span><span class="w"> </span>{}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">hitkeep_archive</span><span class="p">:</span><span class="w"> </span>{}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">hitkeep_backups</span><span class="p">:</span><span class="w"> </span>{}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">networks</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">proxy</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">external</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span></span></span></code></pre></div>
</div>
<p>Die wichtigsten Stellen im Detail:</p>
<ul>
<li><strong><code>HITKEEP_PUBLIC_URL</code></strong> ist die öffentliche Adresse, unter der HitKeep erreichbar ist. Daraus
baut die Oberfläche später den Tracking-Snippet und die Links. Sie muss <strong>exakt</strong> der URL
entsprechen, unter der du HitKeep aufrufst – sonst kommst du in eine Login-Schleife.</li>
<li><strong><code>HITKEEP_TRUSTED_PROXIES</code></strong> ist der Knackpunkt hinter einem Reverse Proxy: Ohne diesen Wert
sieht HitKeep als Absender jedes Aufrufs nur die interne IP von Traefik – dann landen <strong>alle</strong>
Besucher als ein einziger. <code>172.16.0.0/12</code> deckt die Docker-Netze ab, sodass HitKeep dem
<code>X-Forwarded-For</code>-Header von Traefik vertraut und die echte Besucher-IP auswertet.</li>
<li><strong><code>loadbalancer.server.port=8080</code></strong> sagt Traefik, dass HitKeep intern auf Port 8080 lauscht.
Der Container veröffentlicht selbst keine Ports nach außen – der Zugriff läuft ausschließlich
über Traefik.</li>
<li>Die vier <strong><code>_PATH</code>-Variablen</strong> legen Datenbank, Daten, Archiv und Backups unter
<code>/var/lib/hitkeep/</code> ab; die passenden <strong>Volumes</strong> sorgen dafür, dass sie ein Update oder
einen Neustart überleben.</li>
</ul>
<h3 id="schritt-3-stack-starten-und-auf-tls-warten">Schritt 3: Stack starten und auf TLS warten</h3>
<p>Starte den Container:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose up -d</span></span></code></pre></div>
</div>
<p>Prüfe nach ein paar Sekunden den Status:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose ps</span></span></code></pre></div>
</div>
<p>Du solltest den Container als <code>healthy</code> sehen – HitKeep bringt einen eigenen Healthcheck mit:</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">NAME      IMAGE                         SERVICE   STATUS                   PORTS
</span></span><span class="line"><span class="cl">hitkeep   pascalebeier/hitkeep:2.12.0   hitkeep   Up 18 minutes (healthy)  7946/tcp, 8080/tcp</span></span></code></pre></div>
</div>
<p>Traefik holt jetzt im Hintergrund das Let&rsquo;s-Encrypt-Zertifikat für deine Domain. Prüfe von
deinem eigenen Rechner aus, dass die Auslieferung des Tracking-Skripts steht:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">curl -sI https://DEINE_DOMAIN/hk.js</span></span></code></pre></div>
</div>
<p>Erwartete Ausgabe (gekürzt) – Status 200 und ein <code>text/javascript</code>-Typ, aggressiv gecacht:</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">HTTP/2 200
</span></span><span class="line"><span class="cl">content-type: text/javascript; charset=utf-8
</span></span><span class="line"><span class="cl">cache-control: public, max-age=31536000, immutable</span></span></code></pre></div>
</div>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>Achtung
  </p>
  <div class="prose-kitchen text-sm">Bekommst du hier ein <code>404</code> von Traefik oder eine Zertifikatswarnung, warte eine Minute (Let&rsquo;s
Encrypt braucht kurz) und prüfe, dass der A-/AAAA-Record deiner Domain wirklich auf den Server
zeigt. Solange das Zertifikat nicht steht, lädt auch das Snippet im Browser nicht.</div>
</div>
<h3 id="schritt-4-admin-konto-anlegen">Schritt 4: Admin-Konto anlegen</h3>
<p>Rufe <code>https://DEINE_DOMAIN</code> im Browser auf. Beim allerersten Start begrüßt dich HitKeep mit der
Ersteinrichtung. Lege hier dein Administrator-Konto an – Name, E-Mail-Adresse und ein Passwort.
Nimm eine lange Passphrase oder ein per Passwortmanager erzeugtes Zufallspasswort; dieses Konto
sieht sämtliche Statistiken und darf nicht an einem schwachen Passwort hängen:</p>
<p><figure class="my-6"><img src="/tutorials/hitkeep-analytics-selbst-hosten/hitkeep-admin-einrichten_hu_17dc7d56166405f8.webp" srcset="/tutorials/hitkeep-analytics-selbst-hosten/hitkeep-admin-einrichten_hu_10a7123bb5eaf6f6.webp 480w, /tutorials/hitkeep-analytics-selbst-hosten/hitkeep-admin-einrichten_hu_17dc7d56166405f8.webp 768w, /tutorials/hitkeep-analytics-selbst-hosten/hitkeep-admin-einrichten_hu_71deefeea56faa5.webp 1200w, /tutorials/hitkeep-analytics-selbst-hosten/hitkeep-admin-einrichten_hu_ef56741b81244438.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/hitkeep-analytics-selbst-hosten/hitkeep-admin-einrichten_hu_b641e9ef8bfb6096.webp"
    alt="HitKeep-Ersteinrichtung: Formular zum Anlegen des Administrator-Kontos mit Vor- und Nachname, E-Mail-Adresse und Passwort." title="Beim ersten Aufruf legst du dein Admin-Konto an."
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Beim ersten Aufruf legst du dein Admin-Konto an.</figcaption></figure></p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-herb-400 bg-herb-50 dark:border-herb-700 dark:bg-herb-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🧑‍🍳</span>Tipp
  </p>
  <div class="prose-kitchen text-sm">Diese Ersteinrichtung ist nur beim allerersten Aufruf offen. Trotzdem gilt: Richte das
Admin-Konto <strong>sofort</strong> nach dem Start ein und lass keinen frisch gestarteten HitKeep-Wizard
ungesichert im Netz stehen.</div>
</div>
<h3 id="schritt-5-website-anlegen-und-tracking-code-holen">Schritt 5: Website anlegen und Tracking-Code holen</h3>
<p>Nach dem Login klickst du links oben bei <strong>Sites</strong> auf das Plus und legst deine Website an –
als Domain trägst du die Domain der Seite ein, die du messen willst (z. B. <code>DEINE_WEBSITE</code>).</p>
<p>Öffne dann die Site-Einstellungen und wechsle auf den Reiter <strong>Tracking</strong>. Dort findest du den
<strong>Live tracking verifier</strong> (der auf den ersten Treffer wartet) und die Konfiguration des
Tracking-Codes samt Tracker-Host:</p>
<p><figure class="my-6"><img src="/tutorials/hitkeep-analytics-selbst-hosten/hitkeep-tracking-code_hu_dc6a283eb5b165ae.webp" srcset="/tutorials/hitkeep-analytics-selbst-hosten/hitkeep-tracking-code_hu_bc41135cf48424d3.webp 480w, /tutorials/hitkeep-analytics-selbst-hosten/hitkeep-tracking-code_hu_dc6a283eb5b165ae.webp 768w, /tutorials/hitkeep-analytics-selbst-hosten/hitkeep-tracking-code_hu_c3d82fe0876941d.webp 1200w, /tutorials/hitkeep-analytics-selbst-hosten/hitkeep-tracking-code_hu_aa79f4d88d44e8cc.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/hitkeep-analytics-selbst-hosten/hitkeep-tracking-code_hu_87dfd87be9a39e96.webp"
    alt="HitKeep-Tracking-Einstellungen: Live-Verifier wartet auf den ersten Treffer, darunter die Konfiguration des Tracking-Codes mit Tracker-Host und Optionen wie DNT und Web Vitals." title="Der Tracking-Reiter liefert das Snippet und prüft live, ob Treffer ankommen."
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Der Tracking-Reiter liefert das Snippet und prüft live, ob Treffer ankommen.</figcaption></figure></p>
<p>Der einzubauende Code besteht aus einer einzigen Zeile. HitKeep braucht <strong>keine Site-ID</strong> im
Snippet – die Zuordnung passiert automatisch über die Domain der Seite, auf der das Skript läuft:</p>
<div class="sk-code">
  <span class="sk-code-head">HTML</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span> <span class="na">async</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;https://DEINE_DOMAIN/hk.js&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span></span></span></code></pre></div>
</div>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>Hinweis
  </p>
  <div class="prose-kitchen text-sm">Wichtig ist der Unterschied zwischen <strong>Tracker-Host</strong> und <strong>gemessener Domain</strong>: <code>hk.js</code> wird
von deiner HitKeep-Domain (<code>DEINE_DOMAIN</code>) geladen, zugeordnet wird der Treffer aber der Domain
der besuchten Seite (<code>DEINE_WEBSITE</code>). Beide dürfen unterschiedlich sein – die in HitKeep
angelegte Site muss nur zum Hostnamen der besuchten Seite passen.</div>
</div>
<p>Automatisches Event-Tracking (ausgehende Klicks, Downloads, Formular-Absendungen) ist
standardmäßig aktiv. Optional kannst du auf demselben Reiter „Web Vitals&quot; einschalten, um
Ladezeiten (LCP, INP, CLS, FCP, TTFB) mitzumessen, oder „Collect DNT&quot; aktivieren, wenn du auch
Besucher mit „Do Not Track&quot; zählen willst – aus Datenschutzsicht ist die Voreinstellung (DNT
respektieren) die sauberere.</p>
<h3 id="schritt-6-tracking-code-in-die-website-einbauen">Schritt 6: Tracking-Code in die Website einbauen</h3>
<p>Füge die Snippet-Zeile aus Schritt 5 in den <code>&lt;head&gt;</code> deiner Website ein – bei einer statischen
Seite direkt ins HTML-Template, bei einem CMS in den Kopfbereich bzw. ein „Custom HTML&quot;-Feld.
Durch das <code>async</code>-Attribut blockiert das Skript den Seitenaufbau nicht.</p>
<p>Rufe danach eine Seite deiner Website im Browser auf. Der <strong>Live tracking verifier</strong> aus
Schritt 5 sollte innerhalb weniger Sekunden von „Waiting&quot; auf einen ersten Treffer springen –
das ist die Bestätigung, dass die Kette Website → <code>hk.js</code> → HitKeep steht.</p>
<h3 id="schritt-7-das-dashboard-prüfen">Schritt 7: Das Dashboard prüfen</h3>
<p>Sobald Treffer eintrudeln, füllt sich das Dashboard. Unter <strong>Dashboard</strong> siehst du die
Kennzahlen deiner Website – Live-Besucher, Seitenaufrufe, eindeutige Sitzungen, Absprungrate,
Verweildauer und den Traffic-Verlauf:</p>
<p><figure class="my-6"><img src="/tutorials/hitkeep-analytics-selbst-hosten/hitkeep-dashboard_hu_20fed96fa1b9aa0e.webp" srcset="/tutorials/hitkeep-analytics-selbst-hosten/hitkeep-dashboard_hu_662414d46c29959.webp 480w, /tutorials/hitkeep-analytics-selbst-hosten/hitkeep-dashboard_hu_20fed96fa1b9aa0e.webp 768w, /tutorials/hitkeep-analytics-selbst-hosten/hitkeep-dashboard_hu_4d9ecf744e854a2f.webp 1200w, /tutorials/hitkeep-analytics-selbst-hosten/hitkeep-dashboard_hu_d35548a457f25bc.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/hitkeep-analytics-selbst-hosten/hitkeep-dashboard_hu_92a92986f140919f.webp"
    alt="HitKeep-Dashboard mit Kennzahlen-Kacheln (Live-Besucher, Seitenaufrufe, eindeutige Sitzungen, Absprungrate) und einem Traffic-Verlaufsdiagramm für den aktuellen Tag." title="Das Dashboard bündelt die wichtigsten Kennzahlen und den Traffic-Verlauf."
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Das Dashboard bündelt die wichtigsten Kennzahlen und den Traffic-Verlauf.</figcaption></figure></p>
<p>Weiter unten listet <strong>Latest Hits</strong> die einzelnen Aufrufe mit Pfad, Zeitpunkt, Referrer und
Gerät auf – hier siehst du auf einen Blick, über welche Suchmaschinen und Verweise deine
Besucher kommen:</p>
<p><figure class="my-6"><img src="/tutorials/hitkeep-analytics-selbst-hosten/hitkeep-latest-hits_hu_3e42239dd25f7ebe.webp" srcset="/tutorials/hitkeep-analytics-selbst-hosten/hitkeep-latest-hits_hu_4876f6c928f4581e.webp 480w, /tutorials/hitkeep-analytics-selbst-hosten/hitkeep-latest-hits_hu_3e42239dd25f7ebe.webp 768w, /tutorials/hitkeep-analytics-selbst-hosten/hitkeep-latest-hits_hu_c8a10421fd2e6fc4.webp 1200w, /tutorials/hitkeep-analytics-selbst-hosten/hitkeep-latest-hits_hu_b3e324401e709011.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/hitkeep-analytics-selbst-hosten/hitkeep-latest-hits_hu_99f80a189f8ddb68.webp"
    alt="HitKeep-Tabelle „Latest Hits&quot; mit einzelnen Seitenaufrufen, Referrern wie Suchmaschinen sowie dem Gerätetyp je Aufruf." title="Latest Hits zeigt jeden einzelnen Aufruf mit Referrer und Gerät."
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Latest Hits zeigt jeden einzelnen Aufruf mit Referrer und Gerät.</figcaption></figure></p>
<p>Damit steht deine selbst gehostete Statistik: Jeder Aufruf deiner Website landet direkt in
deiner eigenen Datenbank, ohne Umweg über Dritte.</p>
<h3 id="schritt-8-mehr-als-nur-seitenaufrufe">Schritt 8: Mehr als nur Seitenaufrufe</h3>
<p>Für den Anfang reichen Seitenaufrufe und Referrer – HitKeep kann aber deutlich mehr, und die
Bausteine dafür findest du in der linken Navigation. Ein paar, die sich für die meisten Seiten
lohnen:</p>
<ul>
<li><strong>Goals (Ziele):</strong> Definiere ein Ereignis als Ziel – etwa das Absenden eines Kontaktformulars
oder einen Klick auf „Kaufen&quot;. So misst du nicht nur, <em>wie viele</em> kommen, sondern <em>wie viele
das tun, was du willst</em>.</li>
<li><strong>Funnels (Trichter):</strong> Verkette mehrere Schritte (Startseite → Produktseite → Warenkorb) und
sieh, an welcher Stelle Besucher abspringen.</li>
<li><strong>Events:</strong> Neben den automatisch erfassten Ereignissen (ausgehende Klicks, Downloads,
Formulare) kannst du eigene Ereignisse aus deinem Frontend senden.</li>
<li><strong>Web Vitals:</strong> Schaltest du sie im Tracking-Reiter ein, siehst du echte Ladezeiten deiner
Besucher (LCP, INP, CLS) statt synthetischer Laborwerte.</li>
<li><strong>UTM:</strong> Kampagnen-Parameter (<code>utm_source</code>, <code>utm_medium</code>, <code>utm_campaign</code>) werden ausgewertet –
praktisch, um Newsletter- oder Social-Reichweite auseinanderzuhalten.</li>
<li><strong>Email Reports:</strong> Lass dir eine Zusammenfassung regelmäßig per E-Mail schicken, statt selbst
ins Dashboard schauen zu müssen.</li>
</ul>
<p>Eine einzelne HitKeep-Instanz verwaltet außerdem <strong>beliebig viele Websites</strong>: Über das Plus bei
<strong>Sites</strong> legst du weitere an, jede mit eigenem Snippet und eigenem Dashboard. Du brauchst also
keinen zweiten Container, wenn du mehrere Projekte messen willst.</p>
<h2 id="wenn-es-nicht-funktioniert">Wenn es nicht funktioniert</h2>
<div class="troubleshoot not-prose">
<p><strong>Der Live-Verifier bleibt auf „Waiting&quot; / keine Treffer im Dashboard.</strong>
Prüfe im Browser (Entwicklertools → Netzwerk), ob <code>hk.js</code> überhaupt geladen wird und der
Sende-Request danach mit Status 2xx zurückkommt. Häufigste Ursachen: Das Snippet steckt nicht
im HTML, die in HitKeep angelegte Site-Domain passt nicht zum Hostnamen der besuchten Seite,
oder ein Ad-/Tracking-Blocker filtert den Aufruf. Da du unter deiner eigenen Domain hostest
(First-Party), greifen die meisten Blocker nicht – manche Listen kennen aber den Pfad <code>hk.js</code>.</p>
<p><strong>Alle Besucher kommen scheinbar von einer einzigen IP.</strong>
Dann fehlt oder greift <code>HITKEEP_TRUSTED_PROXIES</code> nicht: HitKeep sieht nur Traefiks interne IP.
Stelle sicher, dass die Variable gesetzt ist (<code>172.16.0.0/12</code> deckt die Docker-Netze ab) und
starte den Stack neu (<code>docker compose up -d</code>). Danach werten Besucherzahlen und Herkunft wieder
die echte Client-IP aus dem <code>X-Forwarded-For</code>-Header aus.</p>
<p><strong>Traefik liefert 404 oder 502.</strong>
Ein <code>404</code> heißt meist, dass die Router-Regel nicht greift – prüfe, dass <code>Host(...)</code> deine echte
Domain enthält und der Container im <code>proxy</code>-Netz hängt. Ein <code>502</code> deutet auf den falschen Port:
HitKeep lauscht intern auf <strong>8080</strong>, deshalb muss <code>loadbalancer.server.port=8080</code> gesetzt sein.</p>
<p><strong>Nach dem Login landest du wieder auf der Anmeldeseite (Login-Schleife).</strong>
Das ist fast immer eine Diskrepanz bei <code>HITKEEP_PUBLIC_URL</code>: Der Wert muss exakt der Adresse
entsprechen, über die du HitKeep aufrufst (inklusive <code>https://</code>, ohne abschließenden Slash).
Korrigiere die Variable und starte den Container neu.</p>
<p><strong>Der Container startet nicht bzw. ist nicht <code>healthy</code>.</strong>
Sieh in die Logs: <code>docker compose logs -f hitkeep</code>. Ein fehlendes oder leeres
<code>HITKEEP_JWT_SECRET</code> ist eine typische Startbremse – erzeuge eines wie in Schritt 1 und trage
es ein.</p>

</div>

<h2 id="wartung--backups">Wartung &amp; Backups</h2>
<p><strong>Updates:</strong> HitKeep bewegt sich in der 2.x-Reihe zügig weiter – schau etwa monatlich in die
<a href="https://github.com/pascalebeier/hitkeep/releases">Releases</a>. Für ein Update setzt du den neuen
Tag in der <code>compose.yaml</code> (ersetze <code>2.12.0</code> durch die neue Version) und ziehst ihn:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose pull <span class="o">&amp;&amp;</span> docker compose up -d</span></span></code></pre></div>
</div>
<p>Weil die Daten in Volumes liegen, bleiben deine Statistiken dabei erhalten. Pinne die Version
bewusst auf einen festen Tag statt <code>latest</code>, damit ein Neustart dir nicht ungeplant eine neue
Hauptversion unterschiebt.</p>
<p><strong>Backups:</strong> Deine gesamte Statistik steckt in einer eingebetteten DuckDB-Datei (<code>hitkeep.db</code>
samt Write-Ahead-Log <code>hitkeep.db.wal</code>) unter <code>/var/lib/hitkeep/data</code>. Sichere deshalb nicht eine
Einzeldatei, sondern das <strong>komplette Volume <code>hitkeep_data</code></strong> regelmäßig – am saubersten mit
<a href="/tutorials/backups-mit-restic/">restic</a>. Weil diese Dateien im laufenden Betrieb beschrieben
werden, sicherst du sie am konsistentesten, indem du den Container kurz stoppst
(<code>docker compose stop</code>), das Volume sicherst und wieder startest – oder das von HitKeep unter
<code>HITKEEP_BACKUP_PATH</code> abgelegte Backup mit einbeziehst. Ein Backup, das du nie zurückgespielt
hast, ist nur ein Hoffnungsschimmer: Teste die Wiederherstellung einmal auf einem Testsystem.</p>
<p><strong>Aufräumen:</strong> Die Datenbank wächst mit dem Traffic. Behalte die Größe der Volumes im Blick
(<code>docker system df -v</code>) und plane bei viel Traffic genügend Speicher ein.</p>
]]></content:encoded></item></channel></rss>