16 KiB
SuperOffice Connector & GTM Engine ("The Muscle & The Brain")
Dieses Dokument beschreibt die Architektur der Go-to-Market (GTM) Engine, die SuperOffice CRM mit der Company Explorer Intelligence verbindet.
Ziel des Systems ist der vollautomatisierte Versand von hyper-personalisierten E-Mails, die so wirken, als wären sie manuell von einem Branchenexperten geschrieben worden.
1. Das Konzept: "Static Magic"
Anders als bei üblichen KI-Tools, die E-Mails "on the fly" generieren, setzt dieses System auf vorberechnete, statische Textbausteine.
Warum?
- Qualitätssicherung: Jeder Baustein kann vor dem Versand geprüft werden.
- Performance: SuperOffice muss beim Versand keine KI anfragen, sondern nur Felder zusammenfügen.
- Konsistenz: Ein "Finanzleiter im Maschinenbau" bekommt immer dieselbe, perfekte Argumentation – egal bei welchem Unternehmen.
Die E-Mail-Formel
Eine E-Mail setzt sich aus drei statischen Komponenten zusammen, die im CRM (SuperOffice) gespeichert sind:
[1. Opener (Unternehmens-Spezifisch)] + [2. Bridge (Persona x Vertical)] + [3. Social Proof (Vertical)]
- 1. Opener (Der Haken): Bezieht sich zu 100% auf das spezifische Unternehmen und dessen Geschäftsmodell.
- Quelle:
Company-Objekt (Feld:ai_opener). - Beispiel: "Die präzise Just-in-Time-Fertigung von Müller CNC erfordert einen reibungslosen Materialfluss ohne Mikrostillstände."
- Quelle:
- 2. Bridge (Die Relevanz): Holt die Person in ihrer Rolle ab und verknüpft sie mit dem Branchen-Pain.
- Quelle:
Matrix-Tabelle (Feld:intro). - Beispiel: "Für Sie als Produktionsleiter bedeutet das, trotz Fachkräftemangel die Taktzeiten an der Linie stabil zu halten."
- Quelle:
- 3. Social Proof (Die Lösung): Zeigt Referenzen und den konkreten Nutzen (Gains).
- Quelle:
Matrix-Tabelle (Feld:social_proof). - Beispiel: "Unternehmen wie Jungheinrich nutzen unsere Transportroboter, um Fachkräfte an der Maschine zu halten und Suchzeiten um 30% zu senken."
- Quelle:
2. Die Datenbasis (Foundation)
Die Qualität der Texte steht und fällt mit der Datenbasis. Diese wird zentral in Notion gepflegt und in den Company Explorer synchronisiert.
A. Verticals (Branchen)
Definiert die Makro-Pains und Gains einer Branche sowie das passende Produkt.
- Beispiel: Healthcare -> Pain: "Pflegekräfte machen Logistik" -> Gain: "Hände fürs Bett" -> Produkt: Service-Roboter.
- Wichtig: Unterscheidung nach Ops-Focus (Operativ vs. Infrastruktur) steuert das Produkt (Reinigung vs. Service).
B. Personas (Rollen)
Definiert die persönlichen Pains einer Rolle.
- Beispiel: Produktionsleiter -> Pain: "OEE / Taktzeit".
- Beispiel: Geschäftsführer -> Pain: "ROI / Amortisation".
3. Die Matrix-Engine (Multiplikation)
Das Skript generate_matrix.py (im Backend) ist das Herzstück. Es berechnet alle möglichen Kombinationen aus Verticals und Personas voraus.
Logik:
- Lade alle Verticals (
V) und Personas (P). - Für jede Kombination
V x P:- Lade
V.PainsundP.Pains. - Generiere via Gemini einen perfekten Satz 2 (Bridge) und Satz 3 (Proof).
- Generiere ein Subject, das den Persona-Pain trifft.
- Lade
- Speichere das Ergebnis in der Tabelle
marketing_matrix.
Ergebnis: Eine Lookup-Tabelle, aus der für jeden Kontakt sofort der passende Text gezogen werden kann.
4. Der "Opener" (First Sentence)
Dieser Baustein ist der einzige, der pro Unternehmen generiert wird (bei der Analyse/Discovery).
Logik:
- Scrape Website-Content.
- Identifiziere das Vertical (z.B. Maschinenbau).
- Lade den Core-Pain des Verticals (z.B. "Materialfluss").
- Prompt: "Analysiere das Geschäftsmodell von [Firma]. Formuliere einen Satz, der erklärt, warum [Core-Pain] für genau dieses Geschäftsmodell kritisch ist."
Ergebnis: Ein Satz, der beweist: "Ich habe verstanden, was ihr tut."
5. SuperOffice Connector ("The Muscle")
Der Connector ist der Bote, der diese Daten in das CRM bringt.
Workflow:
- Trigger: Kontakt-Änderung in SuperOffice (Webhook).
- Enrichment: Connector fragt Company Explorer: "Gib mir Daten für Firma X, Person Y".
- Lookup: Company Explorer...
- Holt den
Openeraus der Company-Tabelle. - Bestimmt
VerticalundPersona. - Sucht den passenden Eintrag in der
MarketingMatrix.
- Holt den
- Write-Back: Connector schreibt die Texte in die UDF-Felder (User Defined Fields) des Kontakts in SuperOffice.
UDF_OpenerUDF_BridgeUDF_ProofUDF_SubjectUDF_UnsubscribeLink
6. Monitoring & Dashboard ("The Eyes")
Das System verfügt über ein integriertes Echtzeit-Dashboard zur Überwachung der Synchronisationsprozesse.
Features:
- Account-basierte Ansicht: Gruppiert alle Ereignisse nach SuperOffice-Account oder Person, um den aktuellen Status pro Datensatz zu zeigen.
- Phasen-Visualisierung: Stellt den Fortschritt in vier Phasen dar:
- Received: Webhook erfolgreich empfangen.
- Enriching: Datenanreicherung im Company Explorer läuft (Gelb blinkend = In Arbeit).
- Syncing: Rückschreiben der Daten nach SuperOffice (Gelb blinkend = In Arbeit).
- Completed: Prozess für diesen Kontakt erfolgreich abgeschlossen (Grün).
- Performance-Tracking: Anzeige der Gesamtdurchlaufzeit (Duration) pro Prozess.
- Fehler-Analyse: Detaillierte Fehlermeldungen direkt in der Übersicht.
- Dark Mode: Modernes UI-Design für Admin-Monitoring.
Zugriff:
Das Dashboard ist über das Company Explorer Frontend (Icon "Activity" im Header) oder direkt unter /connector/dashboard erreichbar.
7. Setup & Wartung
Neue Branche hinzufügen
- In Notion anlegen (Pains/Gains/Produkte definieren).
- Sync-Skript laufen lassen:
python3 backend/scripts/sync_notion_industries.py. - Matrix neu berechnen:
python3 backend/scripts/generate_matrix.py --live.
End-to-End Tests
Ein automatisierter Integrationstest (tests/test_e2e_flow.py) deckt den gesamten Zyklus ab:
- Company Creation: Webhook -> CE Provisioning -> Write-back (Vertical).
- Person Creation: Webhook -> CE Matrix Lookup -> Write-back (Texte).
- Vertical Change: Änderung im CRM -> CE Update -> Cascade zu Personen -> Neue Texte.
Ausführen mittels:
python3 connector-superoffice/tests/test_e2e_flow.py
7. Troubleshooting & Known Issues
Authentication "URL has an invalid label"
Tritt auf, wenn SO_ENVIRONMENT leer ist. Der Client fällt nun automatisch auf sod zurück.
Pydantic V2 Compatibility
Die config.py wurde auf natives Python (os.getenv) umgestellt, um Konflikte mit pydantic-settings in Docker-Containern zu vermeiden.
Address & VAT Sync (WIP)
Der Worker wurde erweitert, um auch City und OrgNumber (VAT) zurückzuschreiben.
Status (21.02.2026): Implementiert, aber noch im Feinschliff. Logs zeigen teils Re-Queueing während das Enrichment läuft.
8. Lessons Learned: Address & VAT Sync (Solved Feb 22, 2026)
Die Synchronisation von Adressdaten stellte sich als unerwartet komplex heraus. Hier die wichtigsten Erkenntnisse für zukünftige Entwickler:
-
Das "OrgNumber"-Phantom:
- Problem: In der API-Dokumentation oft als
OrgNumberreferenziert, akzeptiert die WebAPI (REST) strikt nurOrgNr. - Lösung: Mapping im
worker.pyhart aufOrgNrumgestellt.
- Problem: In der API-Dokumentation oft als
-
Verschachtelte Adress-Struktur:
- Problem: Ein flaches Update auf
PostalAddresswird von der API stillschweigend ignoriert (HTTP 200, aber keine Änderung). - Lösung: Das Update muss die tiefe Struktur respektieren:
Address["Postal"]["City"]UNDAddress["Street"]["City"]. Beide müssen explizit gesetzt werden, um in der UI sichtbar zu sein.
- Problem: Ein flaches Update auf
-
Die "Race Condition" Falle (Atomic Updates):
- Problem: Wenn Adress-Daten (
PUT Contact) und UDF-Daten (PUT Contact/Udef) in separaten API-Aufrufen kurz hintereinander gesendet werden, gewinnt der letzte Call. Da dieser oft auf einem veraltetenGET-Stand basiert (bevor das erste Update durch war), wurde die Adresse wieder mit "Leer" überschrieben. - Lösung: Atomic Update Strategy. Der Worker sammelt alle Änderungen (Adresse, VAT, Vertical, Openers) in einem einzigen Dictionary und sendet genau einen
PUT-Request an den Kontakt-Endpunkt. Dies garantiert Konsistenz.
- Problem: Wenn Adress-Daten (
9. Lessons Learned: Appointment Simulation & Persona Matching
Die Simulation von E-Mails via Terminen (Appointments) erforderte Workarounds für das UI-Verhalten von SuperOffice.
-
Header vs. Description (Die 42-Zeichen-Grenze):
- SuperOffice nutzt im Kalender und in Listen den
MainHeaderals Titel. Dieser ist auf ca. 42 Zeichen begrenzt. - Ist der Titel länger, schneidet SuperOffice ihn ab. Erscheint der Titel inkonsistent, "stiehlt" das UI oft die erste Zeile der
Descriptionals Titel-Ersatz. - Strategie: Wir kürzen den
MainHeaderauf 40 Zeichen und stellen sicher, dass der vollständige Betreff als allererste Zeile in derDescriptionsteht. Danach folgen zwei Newlines. Damit landet der Betreff im UI-Header und die Anrede ("Hallo...") bleibt sicher im Textkörper.
- SuperOffice nutzt im Kalender und in Listen den
-
Mapping-Resilienz (Funktion vs. Titel):
- Jobtitel (Funktion) landen in SuperOffice inkonsistent in den Feldern
JobTitleoderTitle. - Lösung: Der Worker fragt nun beide Felder ab (
person.get("JobTitle") or person.get("Title")), um die Rolle korrekt zuzuweisen.
- Jobtitel (Funktion) landen in SuperOffice inkonsistent in den Feldern
-
Rollen-Dynamik:
- Um zu verhindern, dass alte Rollen (z.B. "Infrastruktur") nach einer Beförderung/Änderung in SuperOffice "kleben" bleiben, führt das System nun bei jeder Namens- oder Funktionsänderung einen Rollen-Reset durch.
10. Lessons Learned: API Optimization & Certification (Feb 24, 2026)
Um die Zertifizierung für den SuperOffice App Store zu erhalten, mussten kritische Performance-Optimierungen durchgeführt werden.
-
Die
getAllRows-Falle:- Problem: SuperOffice monierte in der Validierung API-Calls wie
getAllRows(implizit oft durch Abfragen ganzer Objekte ohne Filter), die unnötige Last verursachen. - Lösung: Implementierung von OData
$select. Wir fordern nun strikt nur die Felder an, die wir wirklich benötigen (z.B.get_person(id, select=['JobTitle', 'UserDefinedFields'])). - Wichtig: Niemals pauschal
get_person()aufrufen, wenn nur die Rolle geprüft werden soll.
- Problem: SuperOffice monierte in der Validierung API-Calls wie
-
PUT vs. PATCH (Safe Updates):
- Problem: Die Verwendung von
PUTzum Aktualisieren von Entitäten (Person/Contact) erfordert, dass das gesamte Objekt gesendet wird. Dies birgt das Risiko, Felder zu überschreiben, die zwischenzeitlich von anderen Benutzern geändert wurden ("Race Condition"), und verursacht unnötigen Traffic. - Lösung: Umstellung auf
PATCH. Wir senden nun nur noch die tatsächlich geänderten Felder (Delta). - Implementierung: Der Worker baut nun ein
patch_payload(z.B.{'Position': {'Id': 123}}) und nutzt den dedizierten PATCH-Endpunkt. Dies wurde explizit von SuperOffice für die Zertifizierung gefordert.
- Problem: Die Verwendung von
11. Production Environment (Live Feb 27, 2026)
Nach erfolgreicher Zertifizierung durch SuperOffice wurde der Connector auf die Produktionsumgebung umgestellt.
- Tenant:
Cust26720 - Environment:
online3(zuvorsod) - Endpoint:
https://online3.superoffice.com/Cust26720/api/v1 - Authentication: Umstellung auf Produktions-Client-ID und -Secret erfolgreich verifiziert (Health Check OK).
Wichtig: SuperOffice nutzt Load-Balancing. Die Subdomain (online3) kann sich theoretisch ändern. Die Anwendung prüft dies dynamisch, aber die Basis-Konfiguration sollte den aktuellen Tenant-Status widerspiegeln.
12. Lessons Learned: Production Migration (Feb 27, 2026)
Der Wechsel von der Staging-Umgebung (sod) zur Produktion (onlineX) brachte spezifische technische Hürden mit sich:
-
Globaler Token-Endpunkt:
- Problem: Mandantenspezifische Subdomains (wie
online3.superoffice.com) akzeptieren oft keine OAuth-Anfragen oder liefern leere Antworten. - Lösung: Für den Token-Refresh muss zwingend der globale Endpunkt
https://online.superoffice.com/login/common/oauth/tokensverwendet werden, unabhängig davon, auf welchem Cluster der Mandant liegt.
- Problem: Mandantenspezifische Subdomains (wie
-
DNS-Präfixe (app- vs. direkt):
- Problem: In der Staging-Umgebung lautet der API-Host meist
app-sod.superoffice.com. In der Produktion wird dasapp-Präfix oft nicht verwendet oder führt zu Zertifikatsfehlern. - Lösung: Der
SuperOfficeClientwurde so flexibilisiert, dass er in der Produktion direkt auf{env}.superoffice.comzugreift.
- Problem: In der Staging-Umgebung lautet der API-Host meist
-
Environment Variables Persistence:
- Problem: Docker-Container behalten Umgebungsvariablen oft im Cache ("Shadow Configuration"), selbst wenn die
.env-Datei geändert wurde. - Lösung: Zwingendes
docker-compose up -d --force-recreatenach Credentials-Änderungen.
- Problem: Docker-Container behalten Umgebungsvariablen oft im Cache ("Shadow Configuration"), selbst wenn die
13. Post-Migration Configuration (Cust26720)
Die Konfiguration in der .env Datei wurde für die Produktion wie folgt finalisiert:
| Funktion | UDF / ID | Entity |
|---|---|---|
| Subject | SuperOffice:19 |
Person |
| Intro Text | SuperOffice:20 |
Person |
| Social Proof | SuperOffice:21 |
Person |
| Unsubscribe | SuperOffice:22 |
Person |
| Campaign Tag | SuperOffice:23 |
Person |
| Opener Primary | SuperOffice:86 |
Contact |
| Opener Sec. | SuperOffice:87 |
Contact |
| Vertical | SuperOffice:83 |
Contact |
| Summary | SuperOffice:84 |
Contact |
| Last Update | SuperOffice:85 |
Contact |
14. Kampagnen-Steuerung (Usage)
Das System unterstützt mehrere Outreach-Varianten über das Feld MA_Campaign (Person).
- Standard: Bleibt das Feld leer, werden die Standard-Texte ("standard") für Kaltakquise geladen.
- Spezifisch: Wird ein Wert gewählt (z.B. "Messe 2026"), sucht der Connector gezielt nach Matrix-Einträgen mit diesem Tag.
- Fallback: Existiert für die gewählte Kampagne kein spezifischer Text für das Vertical/Persona, wird automatisch auf "standard" zurückgegriffen.
16. Email Sending Implementation (Feb 28, 2026)
A dedicated script create_email_test.py has been implemented to create "Email Documents" directly in SuperOffice via the API. This bypasses the need for an external SMTP server by utilizing SuperOffice's internal document system.
Features:
- Document Creation: Creates a document of type "Ausg. E-Mail" (Template ID 157).
- Activity Tracking: Automatically creates a linked "Appointment" (Task ID 6 - Document Out) to ensure the email appears in the contact's activity timeline.
- Direct Link: Outputs a direct URL to open the created document in SuperOffice Online.
Usage:
python3 connector-superoffice/create_email_test.py <PersonID>
# Example:
python3 connector-superoffice/create_email_test.py 193036
Key API Endpoints Used:
POST /Document: Creates the email body and metadata.POST /Appointment: Creates the activity record linked to the document.
This is the core logic used to generate the company-specific opener.
Goal: Prove understanding of the business model + imply the pain (positive observation).
Du bist ein exzellenter B2B-Stratege und Texter mit einem tiefen Verständnis für operative Prozesse.
Deine Aufgabe ist es, einen hochpersonalisierten, scharfsinnigen und wertschätzenden Einleitungssatz für eine E-Mail an ein potenzielles Kundenunternehmen zu formulieren.
--- Denkprozess & Stilvorgaben ---
1. **Analysiere den Kontext:** Verstehe das Kerngeschäft. Was ist die kritische, physische Tätigkeit vor Ort? (z.B. 'Betrieb von Hochregallagern', 'Pflege von Patienten').
2. **Identifiziere den Hebel:** Was ist der Erfolgsfaktor? (z.B. 'reibungslose Abläufe', 'maximale Hygiene').
3. **Formuliere den Satz (ca. 20-35 Wörter):**
- Wähle einen eleganten, aktiven Einstieg wie 'Speziell im Bereich...' oder 'Der reibungslose Betrieb...'.
- Verbinde die **spezifische Tätigkeit** mit dem **Hebel** und den **geschäftlichen Konsequenzen**.
- **WICHTIG:** Formuliere immer als positive Beobachtung über eine Kernkompetenz. Du implizierst die Herausforderung durch die Betonung der Wichtigkeit.
- **VERMEIDE:** Konkrete Zahlen (z.B. "35 Rutschen"), da diese veraltet sein können. Nutze abstrakte Größen ("weitläufige Anlagen").