# Unternehmen taggen (https://webmetic.de/docs/api/anleitungen/unternehmen-taggen)

Mit dieser Anleitung halten Sie einen Tag in Webmetic auf dem Stand einer Liste aus Ihrem Customer-Relationship-Management (CRM), zum Beispiel Ihrer Zielkunden. Am Ende haben Sie:

- einen Tag wie Zielkunde an allen Unternehmen Ihrer Liste, die Webmetic kennt, auch an Unternehmen, die Ihre Website noch nicht besucht haben
- ein Skript, das neuen Einträgen den Tag gibt und ihn bei entfernten Einträgen wieder entfernt
- die Domains, zu denen Webmetic kein Unternehmen gefunden hat
- den Tag in der Unternehmensliste, im Profil und als Bedingung für Segmente

## Bevor Sie beginnen [#bevor-sie-beginnen]

- **Dauer**: Das Skript ist in wenigen Minuten eingerichtet. Jeder Aufruf antwortet sofort, sodass Sie auf kein Ergebnis warten müssen.
- **Konto**: Sie brauchen ein Webmetic-Konto mit mindestens einer Website. Ohne Website antwortet die API mit `400` und `NO_WEBSITE`. Mit dem Schlüssel eines Partnerkontos vergeben Sie Tags im Partnerkonto selbst, nicht bei Ihren Kunden.
- **Zugang**: Sie brauchen den Schlüssel **Visitor Intelligence**. Ein Schlüssel für Enrichment oder den Data Layer funktioniert hier nicht. Außerdem brauchen Sie cURL oder eine Umgebung für JavaScript oder Python mit `requests`.
- **Rechte**: Nur Admins sehen den Schlüssel unter [**Menü** > **Integrationen** > **API**](https://app.webmetic.de/?menu=api_details) in der Karte **Visitor Intelligence**. Für die Aufrufe selbst brauchen Sie nur den Schlüssel.
- **Plan**: Die Aufrufe funktionieren in jedem Plan und verbrauchen keine Credits.

Wenn Sie die Aufrufe ohne Konto ausprobieren möchten, nutzen Sie den Demo-Schlüssel `wmtc_demo`, der mit den erfundenen Unternehmen dieser Dokumentation antwortet und nichts speichert. Mehr dazu unter [Ohne Konto testen](https://webmetic.de/docs/api/schnellstart#ohne-konto-testen).

## Tag vergeben [#tag-vergeben]

Senden Sie den Namen des Tags und die Domains mit [`POST /company-tags`](https://webmetic.de/docs/api/referenz/company-tags/company-tags-post). Das Feld `tag` hat 1 bis 100 Zeichen, und `domains` nimmt 1 bis 10.000 Einträge auf.

```bash tab="cURL" tab-group="lang"
curl -X POST "https://hub.webmetic.de/company-tags" \
  -H "Authorization: wmtc_IHR_API_SCHLUESSEL" \
  -H "Content-Type: application/json" \
  -d '{"tag": "Zielkunde", "domains": ["bergquell.example", "hagedorn.example", "gibtesnicht.example"]}'
```

```js tab="JavaScript" tab-group="lang"
const res = await fetch('https://hub.webmetic.de/company-tags', {
  method: 'POST',
  headers: {
    Authorization: 'wmtc_IHR_API_SCHLUESSEL', // Visitor Intelligence key
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    tag: 'Zielkunde',
    domains: ['bergquell.example', 'hagedorn.example', 'gibtesnicht.example'],
  }),
});
console.log(res.status, await res.json()); // 200 { tagged: 2, unknown: ['gibtesnicht.example'] }
```

Wenn es den Tag in Ihrem Konto noch nicht gibt, legt Webmetic ihn an, auch wenn keine Domain passt. Der neue Tag erhält die nächste Farbe aus der Farbauswahl des Dashboards, und nur dort können Sie die Farbe ändern.

Groß- und Kleinschreibung spielen beim Namen keine Rolle, sodass `zielkunde` den bestehenden Tag Zielkunde trifft.

Webmetic kürzt jeden Eintrag auf die Hauptdomain. Aus `https://www.bergquell.example/kontakt`, `info@bergquell.example` und `shop.bergquell.example` wird so `bergquell.example`.

Sie ordnen Unternehmen nur über Domains zu, nicht über Unternehmens-ID, Namen oder die ID aus Ihrem CRM.

Die API sucht die Domains unter allen Unternehmen, die Webmetic kennt, und nicht nur unter den Unternehmen, die Ihre Website besucht haben. Ein Unternehmen erhält den Tag deshalb schon vor seinem ersten Besuch und trägt ihn, sobald es Ihre Website besucht. Sie sehen den Tag bei dem Unternehmen auf allen Websites Ihres Kontos.

Der Aufruf fügt den Tag nur hinzu, und andere Tags eines Unternehmens bleiben erhalten. Wenn Sie denselben Aufruf wiederholen, ändert sich nichts. Wenn ein Segment den Tag vorher automatisch vergeben hat, gilt er danach als von Hand vergeben, und das Segment entfernt ihn nicht mehr.

## Antwort auswerten [#antwort-auswerten]

Die API antwortet mit `200` und zwei Feldern:

- **`tagged`**: die Zahl der gefundenen Domains. Domains, deren Unternehmen den Tag schon hatte, zählen mit.
- **`unknown`**: die Einträge, zu denen Webmetic kein Unternehmen gefunden hat oder die keine gültige Domain enthalten. Die API gibt sie unverändert und in Ihrer Reihenfolge zurück.

Webmetic merkt sich unbekannte Domains nicht. Senden Sie diese Einträge deshalb bei jedem Abgleich erneut, wie es das Skript unten tut.

Die Domains in den Beispielen sind erfunden. Mit Ihrem eigenen Schlüssel stehen Einträge mit der Endung `.example` immer in `unknown`.

## Tag entfernen [#tag-entfernen]

Senden Sie denselben Body mit [`DELETE /company-tags`](https://webmetic.de/docs/api/referenz/company-tags/company-tags-delete). Die API antwortet mit `untagged` und `unknown`, und `untagged` zählt auch Domains, deren Unternehmen den Tag nie hatte.

```bash
curl -X DELETE "https://hub.webmetic.de/company-tags" \
  -H "Authorization: wmtc_IHR_API_SCHLUESSEL" \
  -H "Content-Type: application/json" \
  -d '{"tag": "Zielkunde", "domains": ["hagedorn.example"]}'
```

Webmetic entfernt den Tag bei den gefundenen Unternehmen auf allen Websites Ihres Kontos. Dabei spielt es keine Rolle, wer den Tag vergeben hat: Sie im Dashboard, der CSV Tag-Import, ein Segment, eine Integration oder die API.

Der Tag selbst bleibt in Ihrem Konto. Löschen oder umbenennen können Sie ihn nur im Dashboard. Wenn es keinen Tag mit diesem Namen gibt, antwortet die API mit `404` und `TAG_NOT_FOUND`.

Wenn ein Segment, das diesen Tag automatisch vergibt, noch zum Unternehmen passt, vergibt es den Tag bei seiner nächsten Prüfung wieder. Segmente prüfen tagsüber alle 15 Minuten. Ein Tag, den Ihr Skript nachts entfernt, ist in diesem Fall ab dem Morgen wieder vergeben.

## Liste regelmäßig abgleichen [#liste-regelmäßig-abgleichen]

Die API kann Tags nicht auslesen. Ihr Skript merkt sich deshalb die Liste des letzten Laufs und vergleicht sie mit der aktuellen Liste aus Ihrem CRM:

1. Entfernen Sie den Tag bei den Einträgen, die seit dem letzten Lauf aus der Liste gefallen sind.
2. Vergeben Sie den Tag an alle Einträge der aktuellen Liste.
3. Speichern Sie die aktuelle Liste für den nächsten Lauf.

Eine Liste mit bis zu 10.000 Domains passt in einen Aufruf. Größere Listen teilen Sie in solche Blöcke auf und senden einen Aufruf pro Sekunde.

Die API nimmt je Methode eine Anfrage pro Sekunde an, sodass `POST` und `DELETE` getrennt zählen. Wenn Sie schneller senden, antwortet die API mit `429` und `RATE_LIMITED`, und der Header `Retry-After` nennt die Wartezeit. Mehr dazu unter [Anfragelimits](https://webmetic.de/docs/api/anfragelimits).

Sie können den Abgleich auch in [n8n](https://webmetic.de/docs/integrationen/n8n) oder [Make](https://webmetic.de/docs/integrationen/make-und-zapier) bauen. Dafür eignet sich jeder Schritt, der eine HTTP-Anfrage mit JSON-Body senden kann.

Der CSV Tag-Import im Dashboard unter [**Menü** > **Unternehmen** > **CSV Tag-Import**](https://app.webmetic.de/?menu=csv_tag) eignet sich eher für einen einmaligen Abgleich. Er findet nur Unternehmen, die Ihre Website schon besucht haben, und entfernt keine Tags.

## Vollständiges Skript [#vollständiges-skript]

Das Skript verbindet alle Schritte. Ersetzen Sie `crm_domains` durch eine Abfrage Ihres CRM, die für jeden Eintrag die Website oder E-Mail-Adresse liefert. Starten Sie das Skript danach regelmäßig, zum Beispiel einmal pro Nacht.

Das Skript entfernt den Tag zuerst und vergibt ihn danach. So behält ein Unternehmen den Tag, auch wenn sich in Ihrem CRM nur die Schreibweise seiner Domain geändert hat.

Bei einem Fehler nennt das Skript Status und Code und speichert die Liste nicht, sodass der nächste Lauf alles wiederholt.

Wenn Ihr CRM keine Einträge liefert, zum Beispiel bei einer Störung, bricht das Skript ab, statt den Tag überall zu entfernen.

```python
import json
import time
from pathlib import Path

import requests

URL = "https://hub.webmetic.de/company-tags"
HEADERS = {"Authorization": "wmtc_IHR_API_SCHLUESSEL"}  # Visitor Intelligence key
TAG = "Zielkunde"
BATCH = 10_000  # most domains per call
STATE = Path("tag-domains.json")  # the list of the last run


def crm_domains():
    # replace with the query of your CRM: website or email of every record
    return ["bergquell.example", "https://www.hagedorn.example/kontakt", "kronfeld.example"]


def call(method, domains, attempts=5):
    for _ in range(attempts):
        res = requests.request(method, URL, headers=HEADERS, json={"tag": TAG, "domains": domains}, timeout=60)
        if res.status_code == 429:
            retry_after = res.headers.get("Retry-After", "")
            time.sleep(int(retry_after) if retry_after.isdigit() else 1)
            continue
        time.sleep(1)  # one call per second
        if res.ok:
            return res.json()
        try:
            detail = res.json()["detail"]
        except (ValueError, KeyError, TypeError):
            detail = None
        if not isinstance(detail, dict):
            detail = {"error": f"HTTP_{res.status_code}", "message": res.text[:200]}  # for example a proxy error page
        if method == "DELETE" and detail.get("error") == "TAG_NOT_FOUND":
            return {"untagged": 0, "unknown": []}  # the tag was deleted in the dashboard
        raise SystemExit(f"{method} {res.status_code} {detail.get('error')}: {detail.get('message')}")
    raise SystemExit(f"{method} still rate limited after {attempts} attempts")


current = sorted(set(crm_domains()))
if not current:  # for example during a CRM outage
    raise SystemExit("The CRM returned no entries, nothing changed")
previous = set(json.loads(STATE.read_text())) if STATE.exists() else set()
removed = sorted(previous - set(current))

# 1. Remove the tag from entries that left the list
for i in range(0, len(removed), BATCH):
    print("untagged:", call("DELETE", removed[i:i + BATCH])["untagged"])

# 2. Tag every entry of the current list
unknown = []
for i in range(0, len(current), BATCH):
    body = call("POST", current[i:i + BATCH])
    print("tagged:", body["tagged"])
    unknown += body["unknown"]
print("unknown:", unknown)  # sent again on the next run

# 3. Keep the list for the next run
STATE.write_text(json.dumps(current))
```

## Ergebnis im Dashboard prüfen [#ergebnis-im-dashboard-prüfen]

Tags stehen in keiner Antwort der API, weder an den Besuchs-Endpunkten wie `/company` und `/company-sessions` noch in Webhooks, und auch der KI-Assistent kennt sie nicht. Prüfen Sie das Ergebnis deshalb im Dashboard.

In der Unternehmensliste sehen Sie bis zu zwei Tags je Karte, und Webmetic fasst weitere als „+N“ zusammen. Im Profil eines Unternehmens finden Sie alle Tags im Bereich **Tags**.

Segmente mit der Bedingung **Tags** > **Tag** **ist** oder **ist nicht** berücksichtigen Tags aus der API. Das gilt im Dashboard, in den E-Mail-Alerts eines Segments und für den Webhook `segment.entered`.

Ein Tag, den Sie über die API vergeben, löst diesen Webhook aber nicht sofort aus, denn Webmetic prüft ein Unternehmen erst dann erneut, wenn sich seine Daten ändern. In der Praxis ist das sein nächster Besuch. Mehr dazu unter [Webhooks](https://webmetic.de/docs/api/webhooks).

## Nächste Schritte [#nächste-schritte]

- [Tags vergeben](https://webmetic.de/docs/visitor-intelligence/tags): Tags im Dashboard anlegen, umbenennen, einfärben und löschen.
- [Segment anlegen](https://webmetic.de/docs/segmente/segment-builder): Ein Segment bauen, das nur Unternehmen mit Ihrem Tag zeigt.
- [Fehler](https://webmetic.de/docs/api/fehler): Fehlercodes wie `TAG_NOT_FOUND` verstehen und beheben.
