Communitygithub.com

constancetanahrefs/webinar-analyzer

Ein portabler Skill-Spezifikation für den Aufbau eines plattformneutralen Webinar-Analyzer-Dashboards: Anonymisierungs-Gate, Spaltenzuordnung, Einzel- und übergreifende Webinar-Analysen.

Was ist webinar-analyzer?

Dieser Skill bietet eine vollständig spezifizierte, plattformneutrale Blaupause für ein Webinar-Analyse-Dashboard. Anstatt sich auf ein bestimmtes Tool oder eine Export-Plattform (Zoom, Teams, GoToWebinar etc.) festzulegen, definiert er Datenverträge, Validierungsregeln und Berechnungen, sodass Entwickler ihn in jedem beliebigen Tech-Stack (z. B. Flask, FastAPI, Streamlit oder Jupyter Notebooks) implementieren können. Der Skill deckt den gesamten Arbeitsablauf ab: von einem geführten Aufnahmegespräch zur Ermittlung der verwendeten Plattformen, über ein zwingendes Privacy-Gate, das personenbezogene Daten vor der Analyse ablehnt, bis hin zur automatischen Erkennung von Spalten aus hochgeladenen Exporten. Er unterstützt Einzel- und übergreifende Webinar-Analysen, wie z. B. die Verfolgung von wiederkehrenden Teilnehmern, die Analyse der Aufmerksamkeitsspanne, oder die Auswertung von Umfragen und Wiederholungen. Ein zentrales Merkmal ist das automatische Verstecken von Diagrammen, wenn die erforderlichen Daten nicht vorhanden sind. Der Skill enthält detaillierte Referenzen zu Feldanforderungen und Plattform-Beispielexporten, um eine pragmatische, datengesteuerte Entwicklung zu ermöglichen. Entwickler erhalten eine klare Anleitung, wie sie die Benutzer durch die Einrichtung führen und sicherstellen, dass keine persönlichen Daten in das System gelangen.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add constancetanahrefs/webinar-analyzer

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Webinar Analyzer

Ein Tool, das rohe Webinar-Exporte in zwei Arten von Antworten verwandelt:

  1. Pro Webinar — wer kam, wie lange sie blieben, wann sie gingen, wer sie waren, was sie sagten.
  2. Über alle Webinare hinweg — wächst die Teilnehmerzahl, welcher Slot und welches Format funktionieren, wer immer wieder kommt und welche Lob- und Kritikpunkte immer wieder auftauchen.

Dieser Skill ist stack-neutral. Er spezifiziert Datenverträge, Validierungsregeln, Berechnungen und Diagrammsemantiken. Implementieren Sie ihn in dem Web-Stack Ihrer Wahl (Flask/Django/FastAPI + Postgres + eine beliebige Charting-Bibliothek; Streamlit; ein Notebook; ein BI-Tool). Die Referenzimplementierung, aus der diese Anweisungen extrahiert wurden, ist eine Flask + PostgreSQL + ApexCharts App.


Bevor Sie etwas bauen: das Aufnahmegespräch

Nehmen Sie nicht einfach Zoom an. Nehmen Sie nicht einfach YouTube an. Der häufigste Fehler bei diesem Tool ist, das Exportformat einer einzigen Plattform fest zu verdrahten. Der Benutzer nutzt möglicherweise Teams, GoToWebinar, Livestorm, Demio, Webex, Hopin, Riverside, StreamYard, Crowdcast, BigMarker oder einen individuellen Stack und hostet Wiederholungen auf Vimeo, Wistia, dem eigenen CDN oder gar nicht.

Führen Sie diese Sequenz vor dem Schreiben von Code durch:

Schritt 1 — Fragen Sie, welche Plattformen im Spiel sind

Stellen Sie eine kurze Multiple-Choice-Frage:

  • Auf welcher Plattform führen Sie Live-Webinare durch? (Zoom Webinars / Zoom Meetings / Microsoft Teams / GoToWebinar / Livestorm / Demio / Webex / Hopin / BigMarker / Crowdcast / andere)
  • Wo leben die Umfragen nach dem Webinar? (Im Webinar-Tool integriert / Typeform / Google Forms / SurveyMonkey / Hubspot / keine)
  • Wo werden die Aufzeichnungen gehostet, falls vorhanden? (YouTube / Vimeo / Wistia / selbst gehostet / gated Landingpage / keine Aufzeichnungen)
  • Haben Sie Registrierungsdaten getrennt von Anwesenheitsdaten? (Ein kombinierter Export / zwei separate Exporte / nur Registrierung / nur Anwesenheit)

Schritt 2 — Fragen Sie nach einem echten Export, bevor Sie etwas entwerfen

Sagen Sie klar: "Laden Sie einen echten Export von jeder Quelle hoch – Teilnehmer, Umfrage, Aufzeichnung – bei dem die persönlichen Daten bereits entfernt wurden. Ich lese die tatsächlichen Spaltenüberschriften, anstatt zu raten, und sage Ihnen, welche Teile des Dashboards Ihre Daten unterstützen können und welche nicht."

Bestehen Sie darauf. Eine einzige echte Datei beseitigt alle Annahmen. Wenn der Benutzer keine echten Daten teilen kann, bitten Sie ihn, die Kopfzeile plus 2-3 vollständig erfundene Zeilen einzufügen.

Schritt 3 — Führen Sie die Privacy-Gate-Prüfung für die hochgeladene Datei durch

Siehe Privacy Gate (Pflicht). Lehnen Sie die Datei ab, wenn sie ungeschwärzte personenbezogene Daten enthält. Fahren Sie erst mit der Zuordnung fort, wenn eine bereinigte Datei bereitgestellt wurde.

Schritt 4 — Ordnen Sie die Spalten des Benutzers dem kanonischen Schema zu

Zeigen Sie dem Benutzer eine explizite Zuordnungstabelle an (seine Spalte → kanonisches Feld → was es freischaltet) und benennen Sie, was fehlt. Siehe Feldanforderungen und references/platform-exports.md.

Schritt 5 — Teilen Sie ihnen mit, welche Diagramme sie erhalten

Erstellen Sie vor dem Bau einen Bericht über die Verfügbarkeit von Funktionen:

✅ Mit Ihren Daten verfügbar
   Watch-Time-Verteilung, Verlauf der gleichzeitigen Zuschauer, Drop-Erkennung,
   Anwesenheitstrichter, Monatsvergleich, Neu vs. Wiederkehrend.

⚠️  Teilweise verfügbar
   Demografie – Sie haben Land, aber keine Berufsbezeichnung, daher wird der
   Senioritäts-Donut ausgeblendet.

❌ Nicht verfügbar
   Aufzeichnungsanalysen – kein Aufzeichnungsexport. Der Reiter "Aufzeichnungen"
   wird ausgeblendet, bis Sie einen hinzufügen (oder Sie können die Werte manuell
   über die CSV-Vorlage eingeben).

Erstellen Sie niemals ein Diagramm, dessen Eingabedaten nicht existieren. Blenden Sie das gesamte Panel aus und zeigen Sie eine einzeilige Erklärung, welche Daten es aktivieren würden.


Privacy Gate (PFLICHT)

Jede hochgeladene Datei durchläuft eine Schwärzungsprüfung vor dem Parsing, vor der Speicherung, vor der Analyse. Wenn personenbezogene Daten gefunden werden, lehnen Sie die gesamte Datei ab, nennen Sie die beanstandeten Spalten und Zeilennummern und erklären Sie, wie sie geschwärzt werden kann. Importieren Sie niemals teilweise. Anonymisieren Sie niemals automatisch und stillschweigend.

Was als personenbezogene Daten gilt

KategorieErkennung
E-Mail-Adressen[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,} in einer beliebigen Zelle
Telefonnummern(?:\+?\d[\s\-\(\)]{0,2}){7,15} mit ≥7 Ziffern, reine Zeitstempel/IDs ausgenommen
PostanschriftenZelle, die mit Straßenschlüsselwörtern übereinstimmt (`straße
Postleitzahlen\b\d{5}(-\d{4})?\b oder [A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2} wenn der Spaltenname auf einen Ort hindeutet
IP-AdressenIPv4/IPv6-Literal
Behördliche / Zahlungs-IDs\b\d{3}-\d{2}-\d{4}\b (SSN-ähnlich), \b(?:\d[ -]*?){13,16}\b bestandenem Luhn-Check
Verdächtige SpaltennamenKopfzeile, die auf `email

Regeln

  1. Zuerst Kopfzeilen-Scan. Jede Spalte, deren Name mit der Liste der Verdächtigen übereinstimmt, wird markiert, selbst wenn die abgetasteten Zellen leer erscheinen – eine leere Spalte kann morgen befüllt werden.
  2. Scannen Sie jede Zelle jeder Zeile. Keine Stichprobe. Dateien sind klein (tausende Zeilen); ein vollständiger Scan ist billig und ein stichprobenartiger Scan vermittelt trügerische Sicherheit.
  3. Freitext-Umfrageantworten werden ebenfalls gescannt. Leute tippen "mailen Sie mich an [email protected]" in Feedback-Felder. Dies ist die am häufigsten übersehene Undichtigkeit.
  4. Bei der ersten gefundenen Kategorie ablehnen, aber alle melden. Schließen Sie den Scan ab und präsentieren Sie jedes Problem auf einmal, damit der Benutzer die Datei in einem Durchgang reparieren kann.
  5. Schreiben Sie eine abgelehnte Datei niemals auf die Festplatte oder in die Datenbank. Halten Sie sie im Speicher, lehnen Sie ab, verwerfen Sie sie.
  6. Protokollieren Sie die Ablehnung ohne die beanstandeten Werte. Protokollieren Sie nur Spaltennamen und Zeilennummern – niemals die erkannte E-Mail/Telefonnummer selbst.

Zulässige Kennungen (diese führen NICHT zur Ablehnung)

  • Eine stabile pseudonyme Personen-ID – ein Hash, eine UUID oder eine fortlaufende Ganzzahl, die über Dateien hinweg konsistent ist. Dies ist erforderlich für die webinärübergreifende Analyse (siehe unten).
  • Länder-/Regionsnamen, Organisationsnamen, Berufsbezeichnungen, Senioritätsstufen.
  • Zeitstempel, Dauern, Webinar-IDs, Themen-Strings.

Vorlage für Ablehnungsmeldung

❌ Upload abgelehnt – personenbezogene Daten in attendees_march.csv erkannt

  Spalte "Email"           → 412 E-Mail-Adressen (Zeilen 2–413)
  Spalte "Kontaktnummer"   → 88 Telefonnummern  (Zeilen 2, 5, 9, … )
  Spalte "Was können wir verbessern?" → 3 E-Mail-Adressen im Freitext
                                  (Zeilen 47, 112, 288)

Es wurde nichts importiert und die Datei wurde verworfen.

So beheben Sie das Problem:
  1. Ersetzen Sie die Email-Spalte durch eine stabile pseudonyme ID – z.B. einen
     SHA-256-Hash der kleingeschriebenen E-Mail, abgeschnitten auf 16 Zeichen.
     Verwenden Sie für JEDE Datei die GLEICHE Hash-Methode, damit dieselbe Person
     über Webinare hinweg erkennbar ist.
  2. Löschen Sie die Spalte "Kontaktnummer" vollständig – sie wird nie verwendet.
  3. Schwärzen Sie die E-Mail-Adressen in den Freitext-Antworten, behalten Sie
     den Rest des Kommentars.

Laden Sie die bereinigte Datei erneut hoch. Siehe references/anonymisation.md für ein
fertiges Schwärzungs-Skript.

Warum eine stabile pseudonyme ID nicht verhandelbar ist

Die Hälfte des Werts dieses Tools liegt in der webinärübergreifenden Analyse: neue vs. wiederkehrende Teilnehmer, Retention-Kohorten, wiederholte Anmeldungen, Erscheinungsrate pro Person. All das erfordert, dass dieselbe Person über Dateien hinweg erkannt wird, ohne zu wissen, wer sie ist. Teilen Sie dies dem Benutzer bei der Aufnahme explizit mit – wenn sie E-Mails auf leere Werte oder Zufallswerte pro Datei schwärzen, wird jedes webinärübergreifende Diagramm stillschweigend bedeutungslos.

Empfohlen: person_id = sha256(lower(strip(email)) + fixed_salt)[:16], wobei das Salt außerhalb des Datensatzes gespeichert wird. references/anonymisation.md enthält ein einsatzbereites Skript.


Feldanforderungen

Das Dashboard basiert auf einem kanonischen Schema. Die Spalten des Benutzerexports werden darauf abgebildet. Was die Zuordnung nicht füllen kann, ist eine Funktion, die ausgeblendet wird.

Kanonische Entität: webinar (eine Zeile pro Sitzung)

FeldErforderlich?TypSchaltet freiTypische Quellspalte
external_idErforderlichtext, eindeutigAlles – der Join-Schlüssel über Teilnehmer-/Umfrage-/Aufzeichnungsdateien hinwegWebinar-ID, Meeting-ID, Event-ID, Session-ID
topicErforderlichtextAlle Beschriftungen; Kampagnengruppierung von WiederholungenThema, Titel, Veranstaltungsname
start_timeErforderlichtimestampJedes zeitbasierte Diagramm; Monatsvergleich; Tageszeit; der GleichzeitigkeitsverlaufTatsächliche Startzeit, Start, Datum
duration_minutesStark empfohlenintGleichzeitigkeitsverlauf-X-Achse; % der gesehenen SitzungTatsächliche Dauer, Dauer
num_registrantsEmpfohlenintTrichter, Erscheinungsrate (kann durch Zählen von Zeilen abgeleitet werden)# Registrierte, Registriert
unique_viewersEmpfohlenintTageszeit-Diagramm; Reichweiten-Highlight (ableitbar)Einmalige Zuschauer, Teilnehmer
max_concurrentOptionalintSpitzenpublikums-StatistikMaximale gleichzeitige Aufrufe

Zeitzonenregel: Entscheiden Sie einmalig, ob gespeicherte Zeitstempel UTC oder eine feste lokale Zone sind, notieren Sie es im Schema-Kommentar und konvertieren Sie niemals ad hoc. Die Monats-Bucketisierung liest direkt von diesem Feld. Stellen Sie einen manuellen Monats-Override-Mechanismus bereit (siehe Monats-Overrides) für Sitzungen, die kurz nach lokaler Mitternacht für ein Publikum in einer anderen Zeitzone laufen.

Kanonische Entität: attendee_session (eine Zeile pro Person pro Beitritt)

Eine Person, die geht und wiederkommt, erzeugt mehrere Zeilen. Führen Sie niemals beim Import eine Deduplizierung durch – deduplizieren Sie bewusst zur Analysezeit.

FeldErforderlich?TypSchaltet freiTypische Quellspalte
webinar_idErforderlichFKAlles—
person_idErforderlich (pseudonym)textNeu vs. Wiederkehrend, Retention, wiederholte Anmeldungen, PersonendeduplizierungGehashter E-Mail, Teilnehmer-ID
attendedErforderlichboolAnwesend/Abwesend-Verteilung, Trichter, ErscheinungsrateTeilgenommen (Ja/Nein)
is_registrantEmpfohlenboolAbwesend-Kohorte; Trichterabgeleitet aus dem Vorhandensein von Registrierungszeit
join_timeEmpfohlentimestampGleichzeitigkeitsverlauf, Drop-ErkennungBeitrittszeit
leave_timeEmpfohlentimestampGleichzeitigkeitsverlauf, Drop-ErkennungAustrittszeit
minutesEmpfohlenintWatch-Time-Histogramm, durchschnittliche Watch-TimeZeit in Sitzung (Minuten)
country / regionOptionaltextGeografie-Donut, regionale ZeitanalyseLand/Region
organizationOptionaltextKontoebenen-AnsichtOrganisation, Unternehmen
job_titleOptionaltextSenioritäts-Donut (abgeleitet)Jobtitel, Titel, Rolle
source_nameOptionaltextAkquisitionskanal-DonutQuellname, UTM-Quelle, Empfehler
registration_timeOptionaltimestampAnmeldekurven-AnalyseRegistrierungszeit
custom_answersOptionalJSONEin Donut pro RegistrierungsfrageJede nicht erkannte Spalte

Regel für nicht erkannte Spalten: Jede Spalte in der Teilnehmerdatei, die keines der bekannten Felder oben ist, wird als Registrierungsumfragefrage behandelt und in custom_answers als {Frage: Antwort} gespeichert. Jede solche Frage rendert automatisch ihr eigenes Donut-Diagramm. Dadurch funktioniert das Tool auf Plattformen, die Sie noch nie gesehen haben.

Abgeleitetes Feld – seniority: job_title nach Schlüsselworten gruppieren in C-Level / Gründer (ceo, cto, cfo, cmo, coo, chief, founder, owner, president), VP / Direktor (vp, vice president, head of, director), Manager / Lead (manager, lead, principal), Senior IC (senior, sr.), Junior (junior, jr., intern, associate, assistant), sonst Individual Contributor. Das Senioritätsdiagramm vollständig ausblenden, wenn keine Zeile einen Jobtitel hat.

Kanonische Entität: feedback_response (eine Zeile pro Umfrageeinsendung)

FeldErforderlich?TypSchaltet freiTypische Quellspalte
webinar_idErforderlichFKVerbindung von Feedback zur SitzungMeeting/Webinar-ID
person_idOptional (pseudonym)textVerknüpfung von Feedback mit AnwesenheitsverhaltenGehashte E-Mail-Adresse
submitted_atOptionaltimestampReihenfolge, AktualitätÜbermittlungsdatum und -zeit
scoreEmpfohlenint 1–5Zufriedenheitsverteilung + Durchschnitte"Wie nützlich fanden Sie…"
liked_textEmpfohlentextThemen-Cluster für Lob"Was hat Ihnen gefallen…"
improve_textEmpfohlentextThemen-Cluster für Kritik"Was können wir verbessern…"
other_answersOptionalJSONAlles andere, wörtlichverbleibende Fragespalten

Spaltenerkennung: Finden Sie die Score-/Gefallen-/Verbessern-Spalten durch Schlüsselwortabgleich in der Kopfzeile (nützlich/bewerten/score; gefallen/like; verbessern/improve), Groß-/Kleinschreibung ignorieren, erster Treffer gewinnt. Zeigen Sie dem Benutzer die erkannte Zuordnung und lassen Sie ihn sie korrigieren – die Formulierung der Umfragefragen unterscheidet sich in jedem Unternehmen.

Wenn die Umfrage außerhalb der Webinarplattform (Typeform, Google Forms) lebt, enthält sie keine Webinar-ID. Dann fordern Sie den Benutzer auf, entweder ein ausgeblendetes Feld mit der Webinar-ID hinzuzufügen oder das Ziel-Webinar beim Hochladen in der Benutzeroberfläche auszuwählen.

Kanonische Entität: replay_stats (eine Zeile pro Webinar)

Aufzeichnungen sind die am stärksten plattformabhängigen Daten von allen. Unterstützen Sie drei Aufnahmepfade, in dieser Reihenfolge der Präferenz:

  1. API-Konnektor zum Aufzeichnungshost (YouTube Data/Analytics API, Vimeo, Wistia) – nur, wenn der Benutzer einen hat und Anmeldeinformationen bereitstellt.
  2. Natives Analytics-CSV-Export vom Aufzeichnungshost, abgebildet auf die kanonischen Felder.
  3. Manuelle CSV-Vorlage – immer verfügbar, immer die Rückfallebene. Liefern Sie eine herunterladbare Vorlage mit einer Kopfzeile, einem Kommentarblock, der jede Metrik erklärt, und einer Beispielzeile.
FeldErforderlich?TypSchaltet frei
webinar_idErforderlichjoin keyAlles mit Aufzeichnungsbezug
video_id / video_urlOptionaltextDeep-Link zum gehosteten Video; API-Synchronisation
views_day1OptionalintEarly-Demand-Diagramm
views_day7OptionalintSustained-Demand-Diagramm
total_view_hoursOptionalnumericDiagramm zum gesamten Aufzeichnungskonsum
avg_view_duration_secOptionalintDiagramm zum Aufzeichnungs-Engagement
avg_view_percentageOptionalnumericDiagramm zur Aufzeichnungsbindung
likes, comments, shares, subscribers_gainedOptionalintReaktionsstatistiken

Jedes Aufzeichnungsfeld ist optional. Speichern Sie NULL für leere Felder, niemals 0 – eine nicht gemessene Metrik und eine gemessene Null sind semantisch unterschiedlich.


Monats-Overrides

Das Dashboard-Bucketing verwendet standardmäßig das Monat-Jahr aus start_time. Ein Webinar, das am 1. April um 00:15 Uhr MEZ beginnt, wird vom Server als 31. März 23:15 UTC aufgezeichnet. Das Standard-Bucketing würde es im März anzeigen, obwohl das Publikum es als April-Webinar betrachtet.

Bereitstellung: Eine Tabelle oder Benutzeroberfläche, in der für jedes Webinar das Feld display_month manuell gesetzt werden kann (als Text YYYY-MM). Wenn gesetzt, überschreibt dieses Feld das startzeitbasierte Bucketing für dieses Webinar. Lassen Sie es standardmäßig NULL, um das automatische Bucketing zu verwenden.


Konfiguration des kanonischen Schemas

Dies ist eine empfohlene PostgreSQL-Schemadefinition, an die Sie sich in jedem Ziel-Stack anlehnen können:

-- PostgreSQL-Referenzschema – passen Sie die Typen für Ihre DB an

CREATE TABLE webinar (
    webinars_id      SERIAL PRIMARY KEY,
    external_id      TEXT UNIQUE NOT NULL,
    topic            TEXT NOT NULL,
    start_time       TIMESTAMPTZ NOT NULL,
    duration_minutes INT,
    num_registrants  INT,
    unique_viewers   INT,
    max_concurrent   INT,
    display_month    TEXT  -- 'YYYY-MM' oder NULL
);

CREATE TABLE attendee_session (
    attendee_session_id SERIAL PRIMARY KEY,
    webinars_id         INT NOT NULL REFERENCES webinar(webinars_id),
    person_id           TEXT NOT NULL,
    attended            BOOLEAN NOT NULL,
    is_registrant       BOOLEAN,
    join_time           TIMESTAMPTZ,
    leave_time          TIMESTAMPTZ,
    minutes             INT,
    country             TEXT,
    region              TEXT,
    organization        TEXT,
    job_title           TEXT,
    source_name         TEXT,
    registration_time   TIMESTAMPTZ,
    custom_answers      JSONB DEFAULT '{}'::JSONB
);

CREATE TABLE feedback_response (
    feedback_response_id SERIAL PRIMARY KEY,
    webinars_id          INT NOT NULL REFERENCES webinar(webinars_id),
    person_id            TEXT,
    submitted_at         TIMESTAMPTZ,
    score                INT CHECK (score >= 1 AND score <= 5),
    liked_text           TEXT,
    improve_text         TEXT,
    other_answers        JSONB DEFAULT '{}'::JSONB
);

CREATE TABLE replay_stats (
    replay_stats_id       SERIAL PRIMARY KEY,
    webinars_id           INT NOT NULL REFERENCES webinar(webinars_id),
    video_id              TEXT,
    video_url             TEXT,
    views_day1            INT,
    views_day7            INT,
    total_view_hours      NUMERIC,
    avg_view_duration_sec INT,
    avg_view_percentage   NUMERIC,
    likes                 INT,
    comments              INT,
    shares                INT,
    subscribers_gained    INT
);

Diagramm-Semantiken

Definieren Sie jedes Diagramm anhand seiner Eingabe, nicht seiner Bibliothek. Dies ist der Vertrag, den Ihre Implementierung erfüllen muss.

Tageszeit-Wärmekarte („Wann schalten sie ein?“)

Erforderliche Daten: attendee_session.join_time, webinar.start_time.

Achsen: Y = Stunde des Tages (0–23), X = Wochentag (So–Sa). Die Farbe jeder Zelle ist die Gesamtzahl der Sitzungen, die zu dieser Stunde/an diesem Tag begonnen wurden.

Anzahl: Wenn join_time den gesamten Daten fehlt, zeigen Sie ein leeres Panel mit der Aufschrift "Stündlicher Beitrittsverlauf erfordert Join-Timestamps pro Teilnehmer."

Implementierung: Gruppieren Sie die Basis nach date_trunc('hour', join_time), pivotieren Sie nach Stunde + Wochentag und verwenden Sie eine 2D-ApexCharts-Heatmap (oder die Heatmap-Funktion Ihrer Bibliothek).

Liste der nächsten und vergangenen Webinare

Inhalt: Alle Webinare, sortiert nach start_time absteigend, mit drei Aktionen pro Webinar: „Details anzeigen" (leitet zu /{webinar_id} weiter), SVG-Export und CSV-Export der Teilnehmer dieses Webinars.

CSV-Export: Exportieren Sie attendee_session für dieses Webinar mit den Spalten person_id, attended, join_time, leave_time, minutes, country, organization, job_title, custom_answers (als abgeflachte Schlüssel-Wert-Paare).

Trichter: Registriert → Teilgenommen → Mindestens X Minuten

Erforderliche Daten: attendee_session.is_registrant, attended, minutes.

Stufen:

  1. Registriert = # Zeilen mit is_registrant = true.
  2. Teilgenommen = # Zeilen mit attended = true.
  3. ≥ 5 Minuten (frühes Engagement)
  4. ≥ 15 Minuten (Hälfte des Webinars)
  5. ≥ 30 Minuten (Kernpublikum)

Wenn is_registrant für einen Datensatz fehlt, zeigt der Trichter nur die Stufen 2–5, mit einer Notiz "Registrierungsdaten fehlen; Trichter beginnt bei den Teilnehmern."

Prozentsätze: Jede Stufe wird als Prozentsatz der vorherigen Stufe angezeigt (z. B. 60 % der Teilnehmer blieben ≥5 Minuten).

Verteilung der Watch-Time (Histogramm)

Erforderliche Daten: attendee_session.minutes.

Bucket-Definition: [0, 5), [5, 10), [10, 15), [15, 20), [20, 25), [25, 30), [30, 35), [35, 40), [40, 45), [45, ∞).

Leerer Fall: „Histogramm der Watch-Time erfordert Minuten pro Teilnehmer – geben Sie die Spalte entsprechend an (üblich: ‚Zeit in Sitzung (Min.)', ‚Anwesend (Min.)')."

Verlauf der gleichzeitigen Zuschauer

Erforderliche Daten: join_time und leave_time.

Achsen: X = Minuten relativ zum Start (0 = Startzeit), Y = Anzahl der gleichzeitigen Sitzungen. Der Wertebereich X erstreckt sich vom frühesten bis zum spätesten Join/Leave für das ausgewählte Webinar. Der Anfangsbalken bei t=0 enthält alle Personen, die einen Join-Zeitpunkt vor oder gleich dem Webinar-Startzeitpunkt haben. Der letzte Balken enthält alle Personen, die danach beigetreten sind und noch anwesend sind.

Formel (SQL-Version): Erzeugen Sie für jede ganze Minute zwischen min(join_time) und max(leave_time) einen Bucket und zählen Sie die Zeilen, bei denen join_time <= bucket_time und (leave_time IS NULL oder leave_time > bucket_time).

Erforderlich für diesen Graphen: join_time MUSS ausgefüllt sein. Wenn leave_time vollständig fehlt, zeigen Sie eine Warnung: "Austrittszeit nicht verfügbar – die Kurve der gleichzeitigen Zuschauer nähert sich nur über die Beitrittszeiten an." Auch dann wird der Graph gezeichnet; er zeigt das kumulative Publikum im Laufe der Zeit, keine echte Gleichzeitigkeit.

**Wenn join_time für alle Zeilen fehlt, zeigen Sie: "Die Timeline der gleichzeitigen Zuschauer erfordert Join-Timestamps pro Teilnehmer."

Drop-Erkennung („Wo steigen sie aus?")

Erforderliche Daten: join_time und leave_time.

Implementierung: Dasselbe wie der Verlauf der gleichzeitigen Zuschauer, überlagert mit einem gleitenden Durchschnitt der Änderungsrate (berechnet als delta_y / delta_t in Einheiten von Zuschauern pro Minute). Markieren Sie die 3 Zeitpunkte mit der steilsten negativen Steigung (die häufigsten Ausstiegsmomente). Zeigen Sie diese 3 Zeitpunkte innerhalb eines Tooltips oder als Liste unter dem Graphen an: "Höchste Ausstiegsrate um Minute X (Y Zuschauer/Minute verloren)."

Leerer Fall: Gleich wie bei gleichzeitigen Zuschauern, plus: „Drop-Erkennung erfordert sowohl Join- als auch Leave-Timestamps."

Monatliches Wachstum („Wächst das Publikum?")

Erforderliche Daten: webinar.start_time, attendee_session.attended.

Achsen: X = Monat (YYYY-MM), Y = Anzahl der eindeutigen Personen, die an Webinaren in diesem Monat teilgenommen haben (person_id de-dupliziert nach attended = true).

Zwei Linien: „Einmalige Teilnehmer" (Gesamtzahl der Personen, die diesen Monat mindestens an einem Webinar teilgenommen haben) und „Neue Personen" (Personen, deren erster attended-Datensatz in diesem Monat liegt).

Analyse: Wenn die rote Linie (Neu) sinkt während die blaue Linie (Gesamt) flach bleibt, gewinnen Sie keine neuen Leute, aber die alten kommen wieder. Wenn beide fallen, erodiert Ihr Publikum.

Liniendiagramm: Verwenden Sie den Liniendiagramm-Modus von ApexCharts (oder das Äquivalent Ihrer Bibliothek).

Neu vs. Wiederkehrend (Kohorten-Donut)

Erforderliche Daten: attendee_session.person_id, webinar.start_time.

Definition: Eine Person ist für die aktuelle Webinar-Sitzung „wiederkehrend", wenn sie eine frühere Sitzung mit attended = true hat. Andernfalls ist sie „neu".

Donut: Zwei Segmente: Neu (Anzahl der Personen, die zum ersten Mal teilnehmen) vs. Wiederkehrend (Personen, die zum zweiten, dritten usw. Mal teilnehmen). Berechnen Sie dies pro ausgewähltem Webinar oder aggregiert über alle Zeit.

Wenn person_id komplett fehlt: Zeigen Sie: „Für die Unterscheidung zwischen neuen und wiederkehrenden Teilnehmern ist pro Person eine stabile pseudonyme Kennung erforderlich. Siehe Aufnahme-Anleitung."


Referenzen

  • references/platform-exports.md – Dokumentation der Kanonisierung für jede gängige Export-Plattform.
  • references/anonymisation.md – Bereites Schwärzungs-Skript und Anleitung.
  • references/csv-templates/ – Herunterladbare CSV-Vorlagen für manuelle Eingaben.

Wie Sie diesen Skill in Ihrem eigenen Repository verwenden

Dieses Skill-Repository enthält:

  1. Diese SKILL.md – die vollständige Spezifikation.
  2. references/ – Dokumentation und Skripte.
  3. src/ – Eine Referenzimplementierung (optional, kann geforkt werden).

So starten Sie:

  1. Forken Sie dieses Repo oder kopieren Sie die Ordnerstruktur.
  2. Lesen Sie SKILL.md vollständig.
  3. Implementieren Sie die Aufnahmeschritte in Ihrer Web-App Ihrer Wahl.
  4. Implementieren Sie das Privacy Gate.
  5. Implementieren Sie die Schemazuordnung und die Diagramm-Semantiken.
  6. Implementieren Sie den Feature-Availability-Report.

Hinweis: Dieser Skill ist für die Verwendung mit AI-Agenten konzipiert. Er kann in jede Sprache und Umgebung integriert werden, die die Spezifikation unterstützt.

Verwandte Skills