Candidate Activity &
Messaging Framework
Ziel ist nicht nur bessere Analytics, sondern eine operative Activity-Layer für den ganzen Candidate Lifecycle: Wer ist aktiv, wer wird gerade warm, wer ist veraltet, wer reagiert auf Newsletter, und wann ist der beste Moment für Reverse Apply, Active Sourcing oder Reaktivierung?
Kernidee: Das Backend bleibt System of Record für Kandidaten, Matches und Messaging-Ausspielung. BigQuery wird System of Record für rohe Aktivitäts-Events und historische Feature-Berechnung. Ein abgeleitetes Candidate Activity Profile wird zurück ins Backend synchronisiert und von CRM, Newsletter, Reverse Apply und später Active Sourcing konsumiert.
Current State im Backend
Aus der aktuellen Codebasis sieht man schon gute operative Bausteine, aber noch keine echte Event-Architektur.
Candidate State
Applier enthält bereits Präferenzen, Qualifikation, job_search_status, Dringlichkeit, Gehalt, Weiterbildung und historische Marker wie is_historical.
Lifecycle & CRM
ApplierHistory und match.History bilden operative History, Aufgaben, Statuswechsel und Kommunikations-Events bereits ab.
Messaging
Newsletter-Selektion läuft heute überwiegend über Match-Daten und Filters in apps/match/utils.py; Unsubs liegen in MessageUnsubscription.
Wichtige Beobachtung
In der inspizierten Backend-Codebasis ist aktuell kein sichtbarer zentraler Raw-Event-Stream und auch keine sichtbare BigQuery-Pipeline für Candidate Activity zu erkennen. Es gibt operative Daten, aber keine durchgehende Activity-Historie über App-Nutzung, CRM-Engagement und Messaging-Reaktionen.
Discovery-Signale fachlich vorhanden
Für Salary- und Distanzsignale gibt es bereits gute Backend-Anker:
SalaryEstimates wird über den ConstantsApiView ausgeliefert,
und im Matching werden distance und duration pro Match berechnet und gespeichert.
Nicht sichtbar gefunden habe ich bislang aber
keine expliziten User-Events, die die Nutzung eines Gehalts- oder Distanz-Tools schon mitschreiben.
Deshalb sollten diese Signale im Framework als
neu zu instrumentierende Discovery-Events behandelt werden.
Implementierte Events in der Applicants App
Übersicht aller aktuell im Frontend (laenk-applicant-app-v2) umgesetzten Events.
Jedes Event wird automatisch mit den Top-Level Schema-Feldern angereichert (app_name = "applicants", session_id, is_logged_in, user_agent) und per Dual-Send parallel an PubSub (Cloud Run → BigQuery) sowie PostHog Analytics übertragen.
Multi-App Identification
Jedes Payload enthält app_name: "applicants" zur sauberen Trennung in BigQuery bei künftigen Multi-App-Streams.
Session Tracking
Organisiert über session_id (UUID in sessionStorage). Bleibt über die gesamte Browser-Sitzung konstant.
Dynamic Auth & Device State
Stellt is_logged_in (dynamisch per Event) und user_agent (navigator.userAgent) auf oberster Ebene bereit.
Retry & Deduplication
Nutzt idempotency_key zur Duplikat-Vermeidung bei HTTP-Retries in Cloud Run und Ingestion Endpoints.
| Domain | Event Name | Beschreibung & Triggermoment | Metadaten (Metadata Payload) |
|---|---|---|---|
| App & Session | app_opened |
Technical App Launch: Feuert bei jedem Anwendungs-Boot/Seitenload. Misst Bildschirmauflösung und Browserumgebung. | screen_resolution, user_agent |
session_started |
Session Entry: Feuert exakt 1x pro neuer session_id (UUID-Erstellung im sessionStorage). Misst Erst-Referrer und Entry. |
referrer |
|
nav_tab_switched |
Oberflächen-Wechsel: Feuert bei Klick auf Haupt-Tabs (Jobs vs. Profil) in der Bottom Nav oder Desktop Nav. | tab_name ("jobs" | "profile") |
|
| Job Discovery | job_list_viewed |
Such- & Feed-Aufruf: Misst Trefferanzahl und Filter-Veränderung im Job-Feed. | total_jobs_count, filtered_jobs_count |
job_viewed |
Job Detail Impression: Aufruf einer konkreten Stellenausschreibung / Match-Karte. | job_id, company_id, match_id, journey_context |
|
job_saved |
Merken: Kandidat speichert/lesezeichenisiert eine Stelle. | job_id, company_id, match_id |
|
job_unsaved |
Entfernen: Kandidat entfernt gemerkte Stelle. | job_id, company_id, match_id |
|
filter_changed |
Filter-Anpassung: Ändern von aktiven Such- oder Match-Filtern im Feed. | filters (Record mit aktiven Filterkriterien) |
|
search_area_changed |
Suchradius: Ändern von Umkreis-Entfernung, PLZ oder Stadt. | max_distance, postcode, city |
|
job_ask_question_clicked |
Rückfrage: Klick auf den "Fragen"-Button auf der Job-Detailseite. | job_id, company_id, match_id |
|
job_calculate_travel_time_clicked |
Fahrzeit-Tool: Klick auf "Genaue Fahrzeit berechnen" auf der Job-Detailseite. | job_id, company_id, match_id |
|
job_calculate_salary_clicked |
Gehalts-Tool: Klick auf "Ungefähres Gehalt berechnen" auf der Job-Detailseite. | job_id, company_id, match_id |
|
job_interest_cta_clicked |
Bewerbungs-Start: Klick auf "Ich bin interessiert!" Haupt-CTA auf der Job-Detailseite (öffnet Modal). | job_id, company_id, match_id, cta_location: "job_details_page" |
|
job_interest_modal_cancelled |
Bewerbungs-Abbrechen: Klick auf "Abbrechen" im Bestätigungs-Modal. | job_id, company_id, match_id, cta_location: "confirmation_modal" |
|
job_interest_modal_confirmed |
Bewerbungs-Abschluss: Klick auf "Ich bin interessiert!" im Bestätigungs-Modal (sendet Bewerbung). | job_id, company_id, match_id, cta_location: "confirmation_modal", list_position |
|
| Profile Surface | profile_viewed |
Profil-Aufruf: Aufruf der Profil-Landingpage. | journey_context (z.B. "direct_navigation") |
profile_section_viewed |
Sektions-Anzeige: Kandidat betritt/sieht eine konkrete Profil-Sektion im Edit-Sheet oder Wizard. | section_key, section_label, mode ("single" | "wizard") |
|
profile_completion_flow_viewed |
Campaign Landing Impression: Aufruf der Profil-Vervollständigungs-Landingpage ("Hey [Name], mach dein Profil fit"). | source ("profile_card" | "deeplink") |
|
profile_completion_flow_started |
Wizard Start: Klick auf "Profil vervollständigen" in der Landingpage zum Start des interaktiven Assistenten. | source ("landing_banner") |
|
profile_completion_flow_dismissed |
Abbrechen/Schließen: Klick auf den Zurück-Pfeil oder "Später — zum Profil" in der Landingpage. | source ("campaign_landing") |
|
company_view_preview_clicked |
Unternehmensansicht: Klick auf "Unternehmensansicht ansehen" CTA. | source ("visibility_card" | "profile_header") |
|
profile_wizard_step_skipped |
Wizard Überspringen: Klick auf "Überspringen" bei einem missing step im Vervollständigungs-Wizard. | step_key, step_index, total_steps |
|
profile_wizard_back_clicked |
Wizard Zurück: Klick auf den Zurück-Pfeil im Vervollständigungs-Wizard zur vorherigen Seite. | current_step_key, target_step_key, current_index |
|
profile_wizard_completed |
Wizard Abschluss: Beenden des Vervollständigungs-Wizard (alle Schritte gelöst vs. Incomplete-Summary). | outcome ("success" | "incomplete"), total_steps_completed, total_steps |
|
profile_updated |
Generisches Update-Fallback bei sonstigen allgemeinen Profiländerungen. | section_key, section_label |
|
| Status & Visibility | job_search_status_updated |
Suchstatus-Update: Aktualisierung des Jobsuche-Status (aktiv, offen, nicht suchend) und Dringlichkeit. Single Source of Truth im JobSearchStatusService. |
section_key: "jobSearchStatus", status, urgency |
active_sourcing_visibility_updated |
Sichtbarkeits-Toggle: Ein-/Ausschalten der anonymen Sichtbarkeit für Arbeitgeber (Reverse Recruiting / Active Sourcing). | is_reverse_recruiting_enabled (boolean) |
|
| Preferences | shift_preferences_updated |
Schichtpräferenz: Speichern von Schichtmodellen (Früh, Spät, Nacht, Wochenende). | section_key: "shiftPreferences", section_label: "Schichtpräferenz" |
working_hours_updated |
Dienstlänge: Speichern der wöchentlichen Arbeitsstunden / Schichtdauer. | section_key: "shiftHour", section_label: "Dienstlänge" |
|
working_type_updated |
Arbeitsumfang: Speichern von Vollzeit / Teilzeit / Minijob. | section_key: "workingType", section_label: "Arbeitsumfang" |
|
position_updated |
Position: Speichern der gewünschten Berufsbezeichnung / Fachposition. | section_key: "position", section_label: "Position" |
|
care_type_updated |
Einrichtungsarten: Speichern von Krankenhaus, Altenpflege, Ambulant etc. | section_key: "careType", section_label: "Einrichtungsarten" |
|
| Qualification | education_updated |
Ausbildung: Speichern von Berufsabschluss / Qualifikation. | section_key: "education", section_label: "Ausbildung" |
continuing_education_updated |
Weiterbildung: Speichern von Fachweiterbildungen / Zertifikaten. | section_key: "continuingEducation", section_label: "Weiterbildungen" |
|
driving_license_updated |
Führerschein: Speichern von Führerscheinklassen (PKW, LKW). | section_key: "driving_license", section_label: "Führerschein" |
|
language_skill_updated |
Sprachkenntnisse: Speichern von Sprachen und Sprachniveau. | section_key: "language", section_label: "Sprachkenntnisse" |
|
personal_data_updated |
Persönliches: Speichern von persönlichen Stammdaten (ohne PII Klartext). | section_key: "personal", section_label: "Persönliches" |
|
document_uploaded |
Dokumenten-Upload: Speichern von Lebenslauf (RESUME), Urkunden, Zertifikaten oder Nachweisen. | source ("PROFILE" | "APPLY-SCREEN"), file_types, file_count |
1. Event Tracking
Das Eventmodell sollte entlang der Candidate Journey strukturiert werden. So bleibt es verständlich, erweiterbar und operativ verwertbar.
| Domain | Core Events | Warum relevant |
|---|---|---|
| App & Session | app_opened, session_started |
Minimales Grundsignal für Recency und Basisaktivität, ohne schon zu viel generisches Event-Rauschen zu erzeugen. |
| Job Discovery | job_list_viewed, job_viewed, job_saved, job_unsaved, filter_changed, search_area_changed, job_ask_question_clicked, job_calculate_travel_time_clicked, job_calculate_salary_clicked, job_interest_cta_clicked, job_interest_modal_cancelled, job_interest_modal_confirmed |
Zeigt Suchintensität, Präferenz-Drift und den Übergang von reiner Exploration zu echter Bewerbungsabsicht. Dazu gehören auch Tools, mit denen Kandidaten prüfen, ob sich ein Job finanziell oder vom Arbeitsweg her lohnt. |
| Profile Surface | profile_viewed, profile_updated |
Generische Oberflächen-Events für die gesamte Profilansicht. Hilfreich für Usage und Funnel-Verständnis, aber bewusst getrennt von den fachlichen Feld-Signalen. |
| Status & Visibility | job_search_status_updated, job_search_urgency_updated, start_date_updated, active_sourcing_visibility_updated |
Hochdynamische Steuerungssignale für CRM, Reaktivierung, Outreach und spätere Active-Sourcing-Freigaben. |
| Preferences | care_type_updated, position_updated, search_area_updated, working_type_updated, shift_preferences_updated, working_hours_updated |
Entspricht den Merkmalsfeldern aus der Präferenz-Zone in Experiment 18, nur ohne Verfügbarkeit: Einrichtungsarten, gesuchte Position, Standort, Arbeitsumfang, Dienst-Präferenzen und bevorzugte Arbeitszeit. Genau diese Felder sollten zyklisch durch CRM bestätigt oder aktualisiert werden. |
| Qualification | education_updated, continuing_education_updated, specialization_updated, language_skill_updated, driving_license_updated, work_experience_updated, work_history_updated, cv_uploaded, document_uploaded |
Eher langsam veränderliche Eignungs- und Nachweisfelder. Wichtig für Profilqualität, Matching und spätere Eignungsfilter. |
| CRM Engagement | newsletter_sent, newsletter_opened, newsletter_clicked, whatsapp_sent, whatsapp_clicked, push_opened, unsubscribe_changed |
Misst Responsiveness und Kanalpräferenz. |
Journey Context
Zusätzlich zur fachlichen Event-Domain sollten wir festhalten, in welchem Produktkontext ein Verhalten oder Update passiert ist. So sehen wir später nicht nur was geändert wurde, sondern auch wie es dazu kam.
Wofür wird das gebraucht?
- Um organische Profilpflege von CRM- oder Flow-getriebenen Updates zu unterscheiden.
- Um später zu analysieren, welche Journeys die beste Profilqualität oder die beste Aktivierung erzeugen.
- Um Messaging-Trigger sauber mit nachgelagertem Verhalten zu verbinden.
| Journey Context | Wann wird es gesetzt? | Beispiele |
|---|---|---|
standalone_profile_edit |
Wenn ein Kandidat direkt im Profil einzelne Daten bearbeitet. | search_area_updated, education_updated |
profile_completion_flow |
Wenn ein Update im Profilvervollständigungs-Flow passiert. | continuing_education_updated, shift_preferences_updated |
preference_refresh_flow |
Wenn Präferenzen zyklisch erneut abgefragt oder bestätigt werden. | working_type_updated, care_type_updated |
email_reactivation |
Wenn ein Kandidat aus einer Reaktivierungs-Mail zurückkommt und dann handelt. | app_opened, job_viewed, profile_completion_flow_started |
crm_prompt |
Wenn das Verhalten aus einem In-App- oder Backend-getriggerten CRM-Hinweis kommt. | job_search_status_updated, salary_tool_used |
job_feed |
Wenn das Verhalten aus der normalen Jobsuche bzw. Feed-Nutzung stammt. | job_list_viewed, job_saved, commute_calculated |
Beispiel
Wenn ein Kandidat im Profilvervollständigungs-Flow seine Weiterbildung ergänzt,
speichern wir fachlich event_domain = qualification und zusätzlich
journey_context = profile_completion_flow.
So bleibt die inhaltliche Änderung sauber klassifiziert, und gleichzeitig bleibt die Herkunft des Updates erhalten.
2. Event Schema
Ich würde ein einziges kanonisches Event-Schema definieren und pro Event nur unterschiedliche Payloads zulassen. Sonst explodieren später BigQuery, dbt und CRM-Logik.
| Feld | Typ | Pflicht? | Beschreibung |
|---|---|---|---|
event_id | UUID | Ja | Eindeutige Event-ID für Dedupe und Replay. |
event_name | string | Ja | Z. B. job_viewed oder newsletter_clicked. |
event_domain | string | Ja | App & Session, Job Discovery, Profile Surface, Status & Visibility, Preferences, Qualification, CRM. |
occurred_at | timestamp | Ja | Zeitpunkt des Nutzerverhaltens (ISO 8601 UTC). |
ingested_at | timestamp | Ja | Zeitpunkt der technischen Annahme in der Pipeline (ISO 8601 UTC). |
app_name | string | Ja | Primärer App-Identifier (z. B. "applicants") zur eindeutigen Zuordnung in Multi-App-BigQuery-Streams. |
is_logged_in | boolean | Ja | Dynamischer Authentifizierungs-Status des Kandidaten im Augenblick der Event-Ausführung. |
user_agent | string | Ja | Browser- & Gerätekennung des Nutzers (navigator.userAgent) für technische Analytics und Device-Segmentierung. |
candidate_user_id | int | string | Ja* | Primäre Candidate-ID; bei anonymen Events kann zunächst nur eine device/session ID vorliegen. |
candidate_applier_id | int | string | Optional | Wenn Event auf konkretem Applier-Datensatz statt nur User liegt. |
session_id | string (UUID) | Ja | Verbindet einzelne Screen- und Click-Events innerhalb einer kontinuierlichen Sitzung (in sessionStorage gespeichert). |
journey_context | string | Optional | Produkt- oder Triggerkontext, in dem das Event passiert ist, z. B. profile_completion_flow, standalone_profile_edit, preference_refresh_flow, job_feed. |
source | string | Ja | Nur technischer Ursprung des Events: web, app, backend, crm, whatsapp, sendgrid. |
channel | string | Optional | Email, Push, WhatsApp, In-App, Backend-Automation. |
job_id | int | string | Optional | Wenn das Event an einem Job hängt. |
company_id | int | string | Optional | Wenn das Event an einem Unternehmen hängt. |
match_id | int | string | Optional | Wenn das Event aus Match-/Reverse-Apply-Logik kommt. |
campaign_id | string | Optional | Interne eindeutige Kampagnen-ID für CRM, Reverse Apply, Reaktivierung oder Paid Acquisition. |
campaign_type | string | Optional | Z. B. newsletter, reverse_apply, reactivation, active_sourcing, paid_acquisition. |
campaign_name | string | Optional | Lesbarer Kampagnenname für CRM, Reporting und Debugging. |
utm_source, utm_medium, utm_campaign | string | Optional | Nur für echte Link-Attribution bei Web-/Email-/WhatsApp-Einstiegen; nicht als primäres Kampagnenmodell missbrauchen. |
campaign_keyword | string | Optional | Legacy-/Brückenfeld, falls bestehende Backend-Logik oder Heyflow-Importe dieses Label weiter benutzen. |
metadata | JSON | Ja | Event-spezifische Details wie Sektions-Keys, alte/neue Werte, Wizard-Fortschritt, Filter etc. |
idempotency_key | string | Ja | Deduplizierungs-Schlüssel (defaults to event_id) zur Vermeidung von Mehrfachverarbeitung bei HTTP-Retries in Cloud Run. |
Empfohlene Vereinfachung
source beschreibt nur, wo das Event technisch herkommt.
campaign_id, campaign_type und optional
utm_* beschreiben dagegen den Messaging- oder Acquisition-Kontext.
So vermeiden wir, dass technische Herkunft und Kampagnenlogik miteinander vermischt werden.
Feld-Level Events oder nur profile_updated?
Ja, ich würde relevante Merkmale auf Feld-Ebene tracken und nicht nur ein generisches profile_updated.
Sonst verliert ihr genau den Mehrwert, später zu verstehen, welche Präferenzen und Qualifikationen sich häufig ändern
und welche Signalgruppen für CRM wirklich funktionieren.
- Pflicht auf Feld-Ebene: alles, was Matching, Messaging oder Active Sourcing direkt beeinflusst.
- Nur generisch: rein kosmetische Änderungen wie Profilbild, Freitext ohne klare operative Nutzung oder UI-only Änderungen.
- Praktische Regel: Wenn ein Feld später Segmentierung, Priorisierung, Ausspielung oder Scoring beeinflussen kann, bekommt es ein eigenes Event.
3. Data Flow
Event Origination
- Frontend/App feuert UI- und Engagement-Events.
- Backend & Frontend feuern State-Change- & Action-Events wie
job_interest_modal_confirmed,job_search_status_updated,newsletter_sent. - CRM-Provider schicken Delivery-, Open- und Click-Events zurück.
Storage Layers
- Raw event store mit append-only Verhalten.
- BigQuery raw tables partitioniert nach
occurred_at. - Feature tables mit 1 Zeile pro Candidate.
- Operational backend table für synchronisierte Activity Features.
Empfohlene End-to-End-Architektur
- Frontend, Backend und Messaging-Provider senden Events in einen zentralen Ingestion-Layer.
- Dieser schreibt jedes Event unverändert in einen Raw Store und parallel nach BigQuery.
- BigQuery baut daraus saubere modellierte Tabellen: Sessions, CRM Engagement, Applications, Profile Changes, Search Intent.
- Stündliche oder tägliche Feature-Jobs berechnen Candidate Activity Features.
- Eine dedizierte Sync-Stufe schreibt nur die operativ benötigten Features zurück ins Backend.
- Messaging liest nicht direkt aus Raw Events, sondern aus dem synchronisierten Activity Profile plus Consent/Operational State.
4. Candidate Activity Profile
Pro Candidate sollte es genau ein abgeleitetes Activity Profile geben, das schnell im Backend konsumierbar ist.
Recency & Engagement
last_active_at, last_job_view_at, last_profile_update_at, sessions_7d, sessions_30d, job_views_7d, job_views_30d
Application Intent
applications_7d, applications_30d, applications_started_30d, reverse_apply_clicks_30d, interested_matches_30d
CRM Responsiveness
newsletter_opens_30d, newsletter_clicks_30d, whatsapp_clicks_30d, push_opens_30d, last_channel_engaged
Profile Freshness
profile_completeness_score, preference_freshness_days, qualification_freshness_days, job_search_status_age_days
Operational Flags
active_last_30d, dormant_90d, high_intent, warm_for_reactivation, eligible_for_active_sourcing
Intent Scaffolding
search_intent_score, candidate_health_score, message_fatigue_score, predicted_response_probability
5. Ownership
Backend
- Operative Candidate-Profile
- Consent / Messaging Permissions
- Messaging-Ausspielung
- Synchronisierte Activity Flags
BigQuery
- Raw Events
- Historische Aggregationen
- Feature Computation
- Training Data für Scores/ML
Analytics / CRM
- Dashboards
- Segmentdefinitionen
- Experiment-Auswertung
- Message Strategy
6. Synchronization
Meine Empfehlung ist ein hybrides Modell:
- Event-driven sofort: heiße Flags wie
last_active_at,job_search_status_updated_at,high_intentnach einer Bewerbung oder einem Reverse-Apply-Click. - Stündlicher Batch: Rolling Windows wie
job_views_7d,newsletter_clicks_30d,applications_30d. - Täglicher Batch: schwerere Scores wie Search Intent Score, Candidate Health Score, Messaging Fatigue und Pro/AS Eligibility.
So bleibt das Backend schlank, aber die operativ wichtigen Dinge werden schnell genug aktualisiert.
7. Messaging Integration
Newsletter
Nicht mehr nur statische Fit-Daten. Stattdessen: offene Kandidaten mit frischen Präferenzen, guter Newsletter-Responsiveness und ohne hohe Message Fatigue.
Reverse Apply
Nur Kandidaten mit hoher Suchintention, recent activity oder bestätigtem Suchstatus. Kein aggressives Pingen bei Schlafenden.
Active Sourcing
Unternehmen sehen nur Kandidaten mit AS-Consent, ausreichender Profilqualität und Activity-Signalen, die auf echte Bereitschaft hindeuten.
Push / Email / WhatsApp
Kanäle werden über last_channel_engaged, Click-Rates und Unsub-Verhalten priorisiert. Ziel: weniger Spam, mehr Relevanz.
Segment-Beispiele
- Hot Searchers: aktiv in den letzten 7 Tagen, Job Views hoch, Reverse Apply oder Bewerbungsstart vorhanden.
- Warm Passive: Status offen, letzte Aktivität < 30 Tage, klickt Newsletter, aber bewirbt sich wenig.
- Stale but Recoverable: keine Aktivität 90+ Tage, aber historisch gute Responsiveness oder hohe Fit-Potenziale.
- Active-Sourcing Ready: Profilqualität hoch, Consent vorhanden, Status aktiv/offen, keine negativen Privacy-Signale.
8. Future-proof Design
Search Intent Score
Wird aus Session-Recency, Job Views, Preference Updates, Applications und Reverse-Apply-Engagement gelernt.
Candidate Health Score
Kombiniert Datenfrische, Matchbarkeit, Responsiveness, Consent und Channel Reachability.
AI Messaging
Personalisierte Prompts und Message-Texte können später sicher auf denselben standardisierten Features aufsetzen.
Customer-facing Active Sourcing
Die gleiche Activity-Layer entscheidet später, welche Kandidaten im Unternehmensprodukt sichtbar, priorisiert oder ausgeblendet werden.
Schwächen der aktuellen Architektur
- Zu statisch: Newsletter- und Outreach-Logik schaut heute primär auf Profil-/Match-Zustand, nicht auf echtes Verhalten.
- Kein Raw Event Layer: Ohne vollständige Eventhistorie fehlen saubere Rolling Windows, Funnel-Abbrüche und Channel-Effekte.
- Zu viel Logik im Operational Backend: Gut für Produkt, aber nicht ideal für historische Analyse und schnelle Experimentation.
- Keine klare Trennung zwischen Operational State und Computed Activity Features.
- Kein standardisiertes Candidate Activity Profile, das alle Messaging-Kanäle gemeinsam nutzen.
MVP Event Proposal zur Bestätigung
Damit wir nicht zu breit starten, würde ich für V1 diese Events wirklich als Pflichtset empfehlen:
- App & Session:
app_opened,session_started - Discovery & Apply:
job_list_viewed,job_viewed,job_saved,filter_changed,job_ask_question_clicked,job_calculate_travel_time_clicked,job_calculate_salary_clicked,job_interest_cta_clicked,job_interest_modal_cancelled,job_interest_modal_confirmed - Intent Signals:
reverse_apply_clicked,match_marked_interested - Profile Surface:
profile_viewed,profile_updated - Status & Visibility:
job_search_status_updated,job_search_urgency_updated,start_date_updated,active_sourcing_visibility_updated - Preferences:
care_type_updated,position_updated,search_area_updated,working_type_updated,shift_preferences_updated,working_hours_updated - Qualification:
education_updated,continuing_education_updated,specialization_updated,language_skill_updated,driving_license_updated,work_experience_updated,cv_uploaded - CRM:
newsletter_sent,newsletter_opened,newsletter_clicked,whatsapp_sent,whatsapp_clicked
Mein Vorschlag: Genau mit diesem Set starten, daraus zuerst ein stündlich aktualisiertes Activity Profile bauen, und erst danach feinere Events wie Scrolltiefe, Impressionen, Recruiting-Outcomes oder Message-Read-State ergänzen.