Besuche täglich exportieren
Exportieren Sie jeden Tag die Besuche des Vortags in eine CSV-Datei, ohne doppelte oder fehlende Besuche.
Mit dieser Anleitung rufen Sie jede Nacht die Besuche der erkannten Unternehmen über die API ab. Am Ende haben Sie:
- eine CSV-Datei pro Tag mit einer Zeile pro Besuch: Unternehmen, Uhrzeit, Zahl der Seiten, Dauer, Quelle und erste Seite
- ein Skript, das jede Nacht läuft und die letzten Tage erneut abruft, damit späte Besuche dazukommen und kein Besuch doppelt erscheint
- auf Wunsch dieselben Zeilen in Ihrer eigenen Datenbank, mit der
session_idals Schlüssel
Bevor Sie beginnen
- Dauer: Die Einrichtung dauert etwa 15 Minuten. Ihre erste volle Datei entsteht nach dem ersten Tag mit erkannten Besuchen.
- Konto: Sie brauchen ein Webmetic-Konto mit mindestens einer Website, auf der Ihr Tracking-Code läuft.
- Zugang: Sie brauchen einen Server oder Rechner, der geplante Aufgaben ausführt, zum Beispiel mit cron. Dort brauchen Sie Python 3 mit der Bibliothek
requests. - Rechte: Das Skript nutzt den Schlüssel Visitor Intelligence, den nur Admins unter Menü > Integrationen > API sehen. Wenn Sie keine Admin-Rechte haben, bitten Sie einen Admin Ihres Kontos um den Schlüssel. Der Schnellstart beschreibt die Schritte.
- Plan: Die API ist in jedem Plan verfügbar, auch im Free-Plan und in der Testphase. Die Abfragen auf dieser Seite kosten keine Credits.
Einen Tag abrufen
GET /company-sessions liefert jedes Unternehmen mit seinen Besuchen und deren Seitenaufrufen. Wenn Sie in from_date und to_date dasselbe Datum eintragen, erhalten Sie genau diesen Tag:
curl "https://hub.webmetic.de/company-sessions?domain=ihre-website.de&from_date=2026-10-14&to_date=2026-10-14" \
-H "Authorization: wmtc_IHR_API_SCHLUESSEL"Schreiben Sie die Domain genau so wie in Ihrem Konto. Sonst antwortet die API mit 403 und API_KEY_NOT_AUTHORIZED.
Ein Datum ohne Uhrzeit steht für einen ganzen Tag in UTC. In Deutschland beginnt dieser Tag um 1 Uhr im Winter und um 2 Uhr im Sommer.
Ein Besuch gehört zu dem Tag, an dem er begonnen hat. Wie Sie stattdessen nach deutscher Zeit abfragen, steht unter Zeiträume und Zeitzonen.
Nutzen Sie feste Daten, nicht gestern oder -1 days. Diese Werte hängen vom Zeitpunkt Ihrer Anfrage ab, und ein zweiter Lauf erhält dann einen anderen Zeitraum.
{
"pagination": [
{ "total": 1, "page_total": 1, "isFirst": true, "current": 1, "isLast": true, "page_size": 10000 }
],
"result": [
{
"company_id": "41ea486a9c95",
"company_name": "Bergquell Mineralbrunnen GmbH",
"company_url": "www.bergquell.example",
"relevance_score": 80.96,
"sessions": [
{
"session_id": "01M4WQFX6YM2X5V8T4N6R1C0DZ",
"timestamp": "2026-10-14T08:12:05.214000",
"utm_source": "linkedin",
"utm_medium": "social",
"utm_campaign": "messe-2026",
"session_duration": 309.0,
"user_data": [
{ "timestamp": "2026-10-14T08:12:05.214000", "document_location": "https://ihre-website.de/preise?utm_source=linkedin&utm_medium=social&utm_campaign=messe-2026", "time_spent": 95.0 },
{ "timestamp": "2026-10-14T08:13:40.214000", "document_location": "https://ihre-website.de/abfuellanlagen", "time_spent": 150.0 },
{ "timestamp": "2026-10-14T08:16:10.214000", "document_location": "https://ihre-website.de/kontakt", "time_spent": 64.0 }
]
}
]
}
]
}Alle Felder finden Sie unter Company, Session und Page View.
Alle Seiten lesen
Eine Seite der Antwort fasst bis zu 10.000 Unternehmen. Wenn mehr Unternehmen Ihre Website besucht haben, verteilt die API sie auf mehrere Seiten.
Fragen Sie deshalb die nächste Seite ab, bis current mindestens page_total ist. Mehr dazu unter Paginierung.
Die Besuchs-Endpunkte von Visitor Intelligence beantworten eine Anfrage pro Sekunde je Endpunkt, und das gilt auch für /company-sessions. Warten Sie zwischen zwei Seiten etwas länger als eine Sekunde.
Bei Status 429 oder 5xx warten Sie und senden Ihre Anfrage erneut. Nach 429 nennt der Header Retry-After die Sekunden bis zum nächsten Versuch.
Bei jedem anderen Status ab 400 hilft eine Wiederholung nicht. Das Skript bricht dann ab und nennt den Fehlercode. Mehr dazu unter Fehler.
Besuche eindeutig speichern
Jeder Besuch hat eine session_id, die für diesen Besuch gleich bleibt, auch wenn später Seitenaufrufe dazukommen. Speichern Sie Besuche deshalb mit der session_id als Schlüssel und überschreiben Sie bestehende Einträge.
- Besuche: Der Schlüssel ist die
session_id. In Ihrer Datenbank schreiben Sie mit einem Upsert, in PostgreSQL zum Beispiel mitON CONFLICT (session_id) DO UPDATE. - Unternehmen: Der Schlüssel ist die
company_id, und diecompany_urldient als zweiter Schlüssel. Dasselbe Unternehmen erscheint an mehreren Tagen, und seine Scores gelten für den Zeitpunkt des Abrufs. - Nicht als Schlüssel: Die
client_idändert sich täglich und verbindet keine Besuche über mehrere Tage.
Weil kein Besuch über Mitternacht UTC hinausreicht, liefern zwei benachbarte Tage nie denselben Besuch. Doppelte Besuche entstehen nur, wenn Sie Tage erneut abrufen, und der Schlüssel session_id fängt sie ab.
Im Free-Plan überspringt das Skript Unternehmen mit blurred: true, denn sie sind verborgen und ihre Besuche enthalten nur session_id und timestamp. Mehr dazu unter Testphase und Free-Plan.
Die letzten Tage erneut abrufen
Webmetic ordnet Besuche laufend zu, nicht in einem Durchlauf pro Nacht. Wenn das Unternehmen schon bekannt ist, sehen Sie einen Besuch nach wenigen Minuten im Dashboard.
Wenn ein Unternehmen zum ersten Mal eine Website mit Webmetic besucht, dauert es länger. Der Besuch erscheint dann mit seiner ursprünglichen Startzeit und damit an einem vergangenen Tag.
Auch Werte wie die Zeit auf der letzten Seite können sich nach dem Besuch noch ändern. Die API kennt aber keinen Parameter für „seit dem letzten Abruf geändert".
Rufen Sie deshalb bei jedem Lauf die letzten Tage erneut ab und überschreiben Sie Ihre Einträge. Sie legen die Zahl der Tage im Skript mit DAYS_BACK selbst fest.
Skript einrichten
Das Skript setzt die Schritte oben um. Es ruft die letzten Tage in UTC ab, speichert jeden Besuch einmal und schreibt jeden dieser Tage neu in eine eigene Datei.
- Speichern Sie das Skript als
webmetic_visits.py, zum Beispiel im Ordner/opt/webmetic. - Ersetzen Sie
ihre-website.dedurch Ihre Domain. - Starten Sie es einmal von Hand mit
WEBMETIC_API_KEY=wmtc_IHR_API_SCHLUESSEL python3 webmetic_visits.py. Das Skript legt den Ordnerwebmetic-visitsmit einer Datei pro Tag an, zum Beispielvisits-2026-10-14.csv.
"""Export the visits of the last days from Webmetic, one CSV file per UTC day."""
import csv
import os
import time
from datetime import datetime, timedelta, timezone
from pathlib import Path
import requests
API_URL = "https://hub.webmetic.de/company-sessions"
API_KEY = os.environ["WEBMETIC_API_KEY"]
DOMAIN = "ihre-website.de"
DAYS_BACK = 3 # your choice: how many past days each run fetches again
OUT_DIR = Path("webmetic-visits")
COLUMNS = ["date", "session_id", "timestamp", "company_id", "company_name", "company_url",
"relevance_score", "pages", "session_duration", "utm_source", "utm_medium",
"utm_campaign", "landing_page"]
def get(params, attempts=5):
"""GET with retries on 429, 5xx and network errors."""
delay = 1
for attempt in range(1, attempts + 1):
try:
res = requests.get(API_URL, params=params, headers={"Authorization": API_KEY}, timeout=120)
except requests.RequestException:
if attempt == attempts:
raise
time.sleep(delay)
delay *= 2
continue
if res.status_code == 429 or res.status_code >= 500:
if attempt == attempts:
res.raise_for_status()
retry_after = res.headers.get("Retry-After", "")
time.sleep(int(retry_after) if retry_after.isdigit() else delay)
delay *= 2
continue
if not res.ok:
# other 4xx: a retry does not help, stop with the error code
raise SystemExit(f"{res.status_code} {res.text}")
return res.json()
def fetch_companies(first_day, last_day):
"""All companies with visits from first_day to last_day (both included)."""
companies, page = [], 1
while True:
body = get({"domain": DOMAIN, "from_date": first_day.isoformat(),
"to_date": last_day.isoformat(), "page": page})
companies += body["result"]
info = body["pagination"][0] # pagination is a list with one object
if info["current"] >= info["page_total"]:
return companies
page += 1
time.sleep(1.1) # 1 request per second
def main():
today = datetime.now(timezone.utc).date()
first_day, last_day = today - timedelta(days=DAYS_BACK), today - timedelta(days=1)
rows = {} # session_id -> row, so every visit is written once
for company in fetch_companies(first_day, last_day):
if company.get("blurred"):
continue # hidden on the Free plan
for session in company.get("sessions", []):
pages = session.get("user_data", [])
rows[session["session_id"]] = {
"date": session["timestamp"][:10],
"session_id": session["session_id"],
"timestamp": session["timestamp"],
"company_id": company["company_id"],
"company_name": company.get("company_name"),
"company_url": company.get("company_url"),
"relevance_score": company.get("relevance_score"),
"pages": len(pages),
"session_duration": session.get("session_duration"),
"utm_source": session.get("utm_source"),
"utm_medium": session.get("utm_medium"),
"utm_campaign": session.get("utm_campaign"),
"landing_page": pages[0].get("document_location") if pages else None,
}
OUT_DIR.mkdir(exist_ok=True)
for offset in range(DAYS_BACK):
day = (first_day + timedelta(days=offset)).isoformat()
day_rows = sorted((r for r in rows.values() if r["date"] == day), key=lambda r: r["timestamp"])
tmp = OUT_DIR / f"visits-{day}.csv.tmp"
with tmp.open("w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=COLUMNS)
writer.writeheader()
writer.writerows(day_rows)
tmp.replace(OUT_DIR / f"visits-{day}.csv") # replaces the file of an earlier run
print(day, len(day_rows), "visits")
if __name__ == "__main__":
main()Weil jeder Lauf die Dateien der abgerufenen Tage neu schreibt, schadet ein zweiter Lauf nicht. Die Spalte date enthält den Tag in UTC und die Spalte landing_page die erste Seite des Besuchs.
Für eine Datenbank ersetzen Sie den Teil mit den Dateien durch einen Upsert mit der session_id als Schlüssel.
Täglich ausführen
Starten Sie das Skript jede Nacht nach etwa 3 Uhr deutscher Zeit, denn dann ist der Vortag in UTC auch im Sommer abgeschlossen.
Diese Zeile für cron startet das Skript um 4:15 Uhr:
15 4 * * * cd /opt/webmetic && WEBMETIC_API_KEY=wmtc_IHR_API_SCHLUESSEL /usr/bin/python3 webmetic_visits.py >> export.log 2>&1Weil cron im Home-Verzeichnis startet, nutzt die Zeile absolute Pfade. Die Uhrzeit gilt in der Zeitzone Ihres Servers.
Rufen Sie den Python-Interpreter auf, in dem requests installiert ist. Sie können Ihren Schlüssel statt in der Zeile auch in einer geschützten Datei ablegen.
Webhooks und Export kombinieren
Empfohlen: Webhooks, wenn Sie schnell reagieren wollen, zum Beispiel mit einer Aufgabe in Ihrem CRM. Webmetic sendet ein Ereignis wenige Minuten, nachdem der Besuch im Dashboard erscheint.
Ein Webhook sendet den Besuch so, wie er beim Anlegen des Ereignisses aussah. Er sendet spätere Seitenaufrufe nicht nach, und ein neuer Webhook meldet keine früheren Besuche.
Der tägliche Export liefert vollständige Besuche und füllt auch vergangene Tage nach. Sie können beides kombinieren: Webhooks für die schnelle Reaktion, den Export für den vollständigen Bestand.
Ohne eigenes Skript sendet Ihnen Webmetic über die Benachrichtigungen an festen Wochentagen eine Liste der Unternehmen per E-Mail, auf Wunsch mit einer CSV-Datei.