Von der Zielgruppe zur Mediastrategie | Use Case zu AIlon in Claude & Co.
Wo erreiche ich meine Zielgruppe? Mit AIlon in ChatGPT, Claude, MCP & Co. Medienkanäle und Werbetrigger analysieren und daraus passende Strategien...
Zielgruppenanalysen müssen nicht in einer separaten Plattform stattfinden. Über die AIlon API lassen sich Analyseprojekte, Zielgruppen und Insights direkt in bestehende Anwendungen, Dashboards oder interne Planungssysteme integrieren.
Der zentrale Vorteil: Nutzerinnen und Nutzer müssen ihre gewohnte Arbeitsumgebung nicht verlassen. Sie können Zielgruppen dort anlegen, wo sie ohnehin arbeiten, die Berechnung durch AIlon starten und die Ergebnisse anschließend direkt im eigenen Interface betrachten.
Auf diese Weise lässt sich AIlon an den eigenen Prozess anpassen. Wir entscheiden selbst, welche Funktionen wir anbieten, welche Insights wir abrufen und wie wir die Ergebnisse darstellen. Aus einer frei formulierten Zielgruppenbeschreibung kann so innerhalb weniger Minuten eine strukturierte Analyse entstehen. Die API bietet dafür programmatischen Zugriff auf dieselben Projekt-, Zielgruppen- und Insight-Daten, die auch im AIlon-Dashboard verwendet werden. Weitere Details enthält die technische Dokumentation zur AIlon API.
In diesem Artikel bauen wir beispielhaft folgende Funktionen auf:
Die vollständige Integrationsdokumentation ist unter ailon.io/integration-dokumentation verfügbar.
Stellen wir uns vor, wir entwickeln eine eigene Marketingplanungsplattform.
Die Nutzerinnen und Nutzer sollen innerhalb dieser Plattform Analyseprojekte verwalten, Zielgruppen definieren und die Ergebnisse in einer standardisierten Ansicht auswerten können. Für diesen Prozess soll kein Wechsel in das AIlon-Dashboard notwendig sein.
Die Plattform besitzt dafür drei zentrale Bereiche.
Hier sehen die Nutzerinnen und Nutzer ihre bisherigen Analyseprojekte.
Über den Button „Neues Analyseprojekt“ können sie ein weiteres Projekt anlegen.
Nach dem Öffnen eines Projekts zeigt die Plattform alle darin enthaltenen Zielgruppen.
Über den Button „Neue Zielgruppe“ können die Nutzerinnen und Nutzer eine weitere Zielgruppe anlegen. Dafür geben sie einen Namen und eine frei formulierte Beschreibung ein.
Beim Öffnen einer Zielgruppe zeigt die Plattform immer dieselben Ergebnisbereiche:
Damit entsteht ein durchgängiger Prozess innerhalb der eigenen Anwendung: von der Zielgruppenbeschreibung über die Berechnung bis zur Darstellung der relevanten Insights.
Unsere Plattform übernimmt die Benutzerführung. AIlon übernimmt die Zielgruppenerstellung, die Berechnung und die Bereitstellung der Insights.
Der grundsätzliche Ablauf sieht so aus:
Listen wie Projekte und Zielgruppen werden paginiert ausgegeben. Die API verwendet dafür die Parameter limit und offset. Zusätzlich zu den eigentlichen items enthält die Antwort die Felder count, limit und offset.
Die AIlon API sollte nicht direkt aus dem Browser aufgerufen werden. Stattdessen kommuniziert das Frontend unserer Plattform ausschließlich mit dem eigenen Backend. Das Backend übernimmt anschließend die Kommunikation mit AIlon.
Unser Plattform-Frontend
|
v
Unser Plattform-Backend
|
v
AIlon Public API
Der wichtigste Grund dafür ist die Sicherheit. Der API-Key darf nicht direkt im JavaScript des Frontends, in einer mobilen App oder in öffentlich einsehbarem Code hinterlegt werden.
Der API-Key ist außerdem an einen AIlon-Benutzer gebunden. Die API liefert deshalb nur Projekte und Zielgruppen, auf die dieser Benutzer auch innerhalb der AIlon-Plattform zugreifen darf.
In unserem Beispiel verwenden wir Python und das Paket requests.
Der API-Key wird als Umgebungsvariable gespeichert und nicht direkt in den Code geschrieben.
import os
import time
from typing import Any
import requests
BASE_URL = "https://dashboard.ailon.io/public-api/v1"
DEFAULT_TIMEOUT = 30
session = requests.Session()
session.headers.update(
{
"Authorization": f"Bearer {os.environ['AILON_API_KEY']}",
"Accept": "application/json",
"Content-Type": "application/json",
}
)
Damit wir nicht bei jedem Aufruf dieselbe Fehlerbehandlung wiederholen müssen, erstellen wir eine kleine Hilfsfunktion:
def api_request(method: str, path: str, **kwargs: Any) -> Any:
response = session.request(
method,
f"{BASE_URL}{path}",
timeout=kwargs.pop("timeout", DEFAULT_TIMEOUT),
**kwargs,
)
response.raise_for_status()
return response.json()
Alle Endpunkte außer /health/ benötigen den API-Key im Authorization-Header. Die Antworten werden im JSON-Format geliefert.
Bei der Einrichtung prüfen wir zunächst, ob die API erreichbar ist.
health_response = requests.get(
f"{BASE_URL}/health/",
timeout=DEFAULT_TIMEOUT,
)
health_response.raise_for_status()
print(health_response.json())
Eine erfolgreiche Antwort sieht beispielsweise so aus:
{ "status": "ok", "api_version": "v1" }
Anschließend prüfen wir mit /whoami/, ob der API-Key gültig ist:
identity = api_request(
"GET",
"/whoami/",
)
print(identity)
Der Aufruf liefert unter anderem Informationen zum Benutzer, zur Organisation und zum verwendeten API-Key.
Diese Prüfungen müssen nicht vor jeder Analyse ausgeführt werden. Sie eignen sich vor allem für die erstmalige Einrichtung, einen Health Check oder das technische Monitoring. /health/ ist der einzige Endpunkt ohne Authentifizierung. /whoami/ ist der empfohlene erste authentifizierte Aufruf.
Beim Öffnen unserer Plattform soll zunächst die Projektübersicht erscheinen. Dafür rufen wir den Endpunkt GET /projects/ auf.
Da die Antwort paginiert ist, bauen wir zuerst eine allgemeine Hilfsfunktion für Listen-Endpunkte:
def get_all_pages(path: str, params: dict[str, Any] | None = None) -> list[dict[str, Any]]:
items: list[dict[str, Any]] = []
params = dict(params or {})
while True:
page = api_request(
"GET",
path,
params={**params, "limit": 1000, "offset": len(items)},
)
page_items = page["items"]
items.extend(page_items)
if not page_items or len(items) >= page["count"]:
return items
Mit dem folgenden Code laden wir alle sichtbaren Projekte. Für die Projektübersicht reduzieren wir die Antwort auf die Felder id, name, updated und die Anzahl der enthaltenen Zielgruppen:
projects = get_all_pages("/projects/")
project_overview = [
{
"id": project["id"],
"name": project["name"],
"updated": project.get("updated"),
"audiences": len(project.get("audience_ids", [])),
}
for project in projects
]
Öffentliche Beispielprojekte können wir über den Parameter public laden:
projects = get_all_pages("/projects/", params={"public": True})
project_overview = [
{
"id": project["id"],
"name": project["name"],
"updated": project.get("updated"),
"audiences": len(project.get("audience_ids", [])),
}
for project in projects
]
Die API liefert alle Projekte, die für den Benutzer des API-Keys sichtbar sind.
Klickt eine Nutzerin oder ein Nutzer in unserer Plattform auf „Neues Analyseprojekt“, öffnet sich beispielsweise ein Formular mit Projektname und Beschreibung.
Das Backend übermittelt diese Angaben anschließend mit POST /projects/ an AIlon.
def create_project(name: str, description: str | None = None) -> dict[str, Any]:
return api_request(
"POST",
"/projects/",
json={"name": name, "description": description}
)
Beispiel:
project = create_project(
name="Abenteurer-Analyse",
description="Zielgruppenanalysen rund um abenteuerlustige
Personen."
)
project_id = project["id"]
{"id": project_id, "name": project["name"]}
Die Antwort enthält direkt die ID des neu angelegten Projekts:
{
"id": 280369,
"name": "Abenteurer-Analyse"
}
Diese project_id speichern wir anschließend in unserer Plattform. Wir benötigen sie für alle weiteren Aufrufe innerhalb des Projekts.
Wenn organisation_id nicht übergeben wird, legt AIlon das Projekt privat an. Mit einer passenden organisation_id kann das Projekt organisationsweit erstellt werden. Der Projektname ist verpflichtend und darf laut API-Dokumentation maximal 100 Zeichen lang sein.
Öffnet eine Nutzerin oder ein Nutzer ein Projekt, soll unsere Plattform alle darin enthaltenen Zielgruppen laden. Dafür verwenden wir den Endpunkt GET /projects/{project_id}/audiences/.
def list_audiences(project_id: int) -> list[dict[str, Any]]: return get_all_pages(f"/projects/{project_id}/audiences/")
Anschließend bereiten wir die Daten für die Übersicht auf:
audiences = list_audiences(project_id) audience_overview = [ { "id": audience["id"], "name": audience["name"], "status": audience.get("status"), } for audience in audiences ]
Da wir das Beispielprojekt erst im vorherigen Schritt erstellt haben, enthält es noch keine Zielgruppen. Die Antwort sieht deshalb zunächst so aus:
[]
Für ein Projekt mit bereits vorhandenen Zielgruppen kann die Antwort beispielsweise so aussehen:
[
{
"id": 186822,
"name": "Einkaufslisten-Verwendende",
"status": "Berechnet"
},
{
"id": 186819,
"name": "Impulsivkaufende",
"status": "Berechnet"
},
{
"id": 186820,
"name": "Kaufentscheidung beeinflusst durch Kinder",
"status": "Berechnet"
}
]
In der Projektdetailseite unserer Marketingplattform soll es nun einen Button „Neue Zielgruppe“ geben. Nach dem Klick öffnet sich ein Formular mit zwei Feldern:
Für unsere Hotelkampagne könnte eine Nutzerin beispielsweise folgende Zielgruppe beschreiben:
Frauen in ihren 30ern mit Universitätsabschluss, die beruflich viel reisen. Eine hohe berufliche Position ist ihnen wichtig. Im Hotel suchen sie Ruhe und Entspannung. Außerdem legen sie großen Wert auf ihre Ernährung.
Die frei formulierte Beschreibung wird als prompt an AIlon übermittelt. Für den weiteren technischen Ablauf verwenden wir durchgängig die Beispielzielgruppe „Nachhaltige Abenteurer“. So bleiben die folgenden API-Antworten und Auswertungen miteinander vergleichbar.
def create_audience(
project_id: int,
name: str,
prompt: str,
) -> dict[str, Any]:
return api_request(
"POST",
f"/projects/{project_id}/generate_audience/",
json={"name": name, "prompt": prompt},
)
Beispiel:
audience = create_audience(
project_id=project_id,
name="Nachhaltige Abenteurer",
prompt=(
"Personen zwischen 20 und 40, denen Nachhaltigkeit und
Umweltbewusstsein wichtig ist und die gleichzeitig
abenteuerlustig sind und Abwechslung suchen."
)
)
audience_id = audience["id"]
{"id": audience_id, "status": audience.get("status")}
Direkt nach dem Aufruf kann die Antwort beispielsweise so aussehen:
{
"id": 472472,
"status": "Wird berechnet."
}
AIlon erstellt aus dem Freitext zunächst die Zielgruppendefinition und startet anschließend die Berechnung. Dieser Prozess läuft asynchron. Unser Backend erhält deshalb sofort eine Zielgruppen-ID, obwohl die eigentlichen Ergebnisse noch nicht bereitstehen.
Neue Zielgruppen können nur in eigenen, bearbeitbaren Projekten angelegt werden. Öffentliche Beispielprojekte sind für diesen Endpunkt schreibgeschützt.
Nach der Erstellung prüft unser Backend regelmäßig den Status der Zielgruppe.
def get_audience(
project_id: int,
audience_id: int,
) -> dict[str, Any]:
return api_request(
"GET",
f"/projects/{project_id}/audiences/{audience_id}/",
)
Für einen einfachen Prototypen können wir die Funktion get_audience nach einigen Sekunden erneut ausführen und prüfen, ob die Zielgruppe bereits berechnet ist:
audience = get_audience(project_id, audience_id)
{"name": audience["name"], "status": audience["status"]}
Die Rückgabe kann dann so aussehen:
{
"name": "Nachhaltige Abenteurer",
"status": "Berechnet"
}
In einer produktiven Plattform sollte ein Worker oder ein interner Job das Warten und die regelmäßige Statusprüfung übernehmen:
def wait_for_audience(
project_id: int,
audience_id: int,
poll_interval: int = 10,
timeout: int = 600,
) -> dict[str, Any]:
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
audience = get_audience(project_id, audience_id)
status = audience["status"].rstrip(".")
if status == "Berechnet":
return audience
if status == "Berechnung fehlgeschlagen":
raise RuntimeError("Die Zielgruppenberechnung ist
fehlgeschlagen.")
if status != "Wird berechnet":
raise RuntimeError(f"Unbekannter Zielgruppenstatus:
{status}")
time.sleep(poll_interval)
raise TimeoutError("Die Zielgruppe wurde nicht rechtzeitig berechnet.")
Die Funktion verwenden wir so:
audience = wait_for_audience(project_id, audience_id)
audience
Die Funktion prüft alle zehn Sekunden, ob die Berechnung abgeschlossen ist. Standardmäßig ist eine Zielgruppe in weniger als zwei Minuten berechnet. Der Timeout ist vorsichtshalber auf zehn Minuten gesetzt. Das entspricht auch dem standardmäßigen Timeout im AIlon-Dashboard.
Sobald die Zielgruppe berechnet ist, gibt die Funktion die Zielgruppendaten zurück. Anschließend können wir Potenzial, Zusammenfassung und Insights laden. Eine mögliche Rückgabe sieht so aus:
{
"id": 472472,
"name": "Nachhaltige Abenteurer",
"description": "Personen zwischen 20 und 40, denen Nachhaltigkeit und Umweltbewusstsein wichtig ist und die gleichzeitig abenteuerlustig sind und Abwechslung suchen.",
"definition_text": "('Alter' von '20 Jahre' bis '40 Jahre') UND (Hohe Wahrscheinlichkeit für 'Achtet beim Kauf auf Nachhaltigkeit' ODER 'Nachhaltigkeit' ODER Hohe Wahrscheinlichkeit für 'Spendet für die Umwelt') UND ('Erlebnishunger' von 'Eher hoch' bis 'Hoch' ODER Hohe Wahrscheinlichkeit für 'Mir ist Freude und Abwechslung wichtig')",
"status": "Berechnet",
"updated_at": "2026-08-24T11:39:43.899Z",
"segments": []
}
Der dokumentierte Status Wird berechnet. steht für eine laufende asynchrone Berechnung. Der Status Berechnung fehlgeschlagen muss dagegen als Fehlerzustand behandelt werden.
Der erste Bereich unserer Zielgruppenauswertung zeigt die Größe der Zielgruppe und eine textbasierte Zusammenfassung. Dafür verwenden wir zwei eigene Endpunkte.
def get_potential(
project_id: int,
audience_id: int,
) -> dict[str, Any]:
return api_request(
"GET",
f"/projects/{project_id}/audiences/{audience_id}/potential/",
)
def get_summary(
project_id: int,
audience_id: int,
) -> str:
paragraphs = api_request(
"GET",
f"/projects/{project_id}/audiences/{audience_id}/summary/",
)
return "\n\n".join(
item["data"]
for item in paragraphs
if item.get("type") == "paragraph" and item.get("data")
)
Anschließend führen wir beide Ergebnisse in einer einfachen Struktur zusammen:
potential = get_potential(project_id, audience_id)
summary = get_summary(project_id, audience_id)
{
"potential_absolute": potential["potential_absolute"],
"potential_percent": round(potential["potential_relative"] * 100, 2),
"summary": summary,
}
Die zusammengeführte Antwort kann beispielsweise so aussehen:
{
"potential_absolute": 3383591,
"potential_percent": 4.99,
"summary": (
'Die Zielgruppe der "Nachhaltigen Abenteurer" besteht aus etwa 3.4 Millionen '
'Personen in Deutschland, was 4.99% der über 18-jährigen Bevölkerung entspricht. '
'Das Durchschnittsalter dieser Gruppe liegt bei 30 Jahren, wobei der Frauenanteil '
'mit 54.91% leicht überwiegt. Ein Großteil der Zielgruppe hat einen hohen Bildungsgrad, '
'da 55.75% das Abitur besitzen und 28.65% Akademiker sind. Diese Gruppe zeigt eine '
'starke Affinität zu beruflichem Erfolg und ist bereit, persönliche Opfer zu bringen, '
'um im Beruf voranzukommen. Sie lassen sich bei Kaufentscheidungen von Prominenten und '
'Influencern beeinflussen und bevorzugen Urlaubsorte mit festgelegten Aktivitäten, '
'nutzen aber auch gerne Last-Minute-Angebote. Finanzielle Angelegenheiten verunsichern '
'sie, und sie verlassen ihre Komfortzone, um beruflich weiterzukommen. Sie haben eine '
'Vorliebe für Pop- und Electronic Dance Music und nutzen gerne Dienste wie Uber Eats. '
'Im Gegensatz dazu meiden sie Urlaub im Heimatland, lokale Sehenswürdigkeiten und '
'haben Sicherheitsbedenken beim Onlinebanking.\n\n'
'Die Ergebnisse deuten darauf hin, dass die "Nachhaltigen Abenteurer" eine dynamische '
'und karriereorientierte Zielgruppe sind, die bereit ist, Risiken einzugehen und neue '
'Erfahrungen zu sammeln, um ihre beruflichen Ziele zu erreichen. Ihre Unsicherheit in '
'finanziellen Angelegenheiten könnte darauf hinweisen, dass sie trotz ihrer Ambitionen '
'und ihres Bildungsniveaus noch Unterstützung und Orientierung in diesem Bereich benötigen.'
),
}
potential_absolute beschreibt die absolute Anzahl der Personen dieser Zielgruppe im Projektuniversum.
Standardmäßig umfasst das Projektuniversum die gesamte deutsche Bevölkerung ab 18 Jahren. Wenn eine Zielgruppe auf einer eigenen Datenintegration in AIlon basiert, entspricht das Projektuniversum stattdessen der jeweiligen Datenbasis dieser Integration.
potential_relative beschreibt den Anteil der Zielgruppe am Projektuniversum. Die API liefert den Wert als Dezimalzahl. Im Beispiel multiplizieren wir ihn mit 100 und runden ihn auf zwei Nachkommastellen.
In eigenen Projekten kann eine erfolgreiche Summary-Anfrage Credits verbrauchen. In öffentlichen Beispielprojekten ist die Anfrage kostenlos.
Potenzial und Zusammenfassung besitzen eigene Endpunkte. Soziodemografie, Werte, Persönlichkeit und Mediennutzung werden dagegen über sogenannte Insights geladen.
Welche Insights aktuell zur Verfügung stehen, ermitteln wir über GET /insights/:
def list_insights() -> list[dict[str, Any]]:
return api_request(
"GET",
"/insights/",
)
insight_catalog = list_insights()
Jeder Eintrag enthält unter anderem folgende Felder:
{
"id": 4093,
"display_name": "Basic | Soziodemografie",
"description": "Geschlecht, Bildung, Anzahl Kinder, …",
"credit_cost": "1.0000"
}
Für unser Plattformbeispiel interessieren uns drei Insight-Pakete:
[
{
"id": 4093,
"display_name": "Basic | Soziodemografie",
"description": "Geschlecht, Bildung, Anzahl Kinder, Bundesländer, Haushaltsnetto, ...",
"credit_cost": "1.0000"
},
{
"id": 4226,
"display_name": "Extended | Gesellschaft, Politik, Werte und Persönlichkeit",
"description": "Extraversion, Nachhaltigkeit, Religion, CDU, ...",
"credit_cost": "3.0000"
},
{
"id": 4160,
"display_name": "Plus | Mediennutzung",
"description": "Nutzungsfrequenz - Instagram: täglich, Nutzung Newsletter - wöchentlich, Nutzung Podcast: monatlich, ..."
"credit_cost": "10.0000"
}
]
Diese Bezeichnungen und die verwendeten Beispiel-IDs stammen aus dem /insights/-Aufruf des Beispiels.
Der technische Aufruf ist für alle drei Insight-Pakete gleich. Da auch die Insight-Berechnung asynchron laufen kann, behandeln wir drei mögliche Zustände:
def get_insight_data(
insight_id: int,
audience_id: int,
poll_interval: int = 5,
timeout: int = 600,
) -> Any:
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
result = api_request(
"GET",
f"/insights/{insight_id}/data/",
params={"audience_id": audience_id},
)
status = result["status"]
if status == "SUCCESS":
return result.get("data")
if status == "ERROR":
raise RuntimeError(
f"Insight fehlgeschlagen: {result.get('error_code')}
– {result.get('error')}"
)
if status != "CALCULATING":
raise RuntimeError(f"Unbekannter Insight-Status:
{status}")
time.sleep(poll_interval)
raise TimeoutError(
f"Insight {insight_id} wurde nicht rechtzeitig berechnet."
)
Beim Status SUCCESS stehen die Ergebnisse im Feld data.
Beim Status CALCULATING übergibt das Backend noch keine Ergebnisse an das Frontend. Stattdessen fragt es den Endpunkt nach dem definierten Intervall erneut ab.
Beim Status ERROR sollten die Felder error und error_code protokolliert werden. AIlon berechnet Credits nur bei einer erfolgreichen Antwort mit dem Status SUCCESS. Ein Zwischenstand mit CALCULATING wird nicht abgebucht.
Nachdem wir die Insight-IDs ermittelt haben, können wir die Soziodemografie abrufen:
sociodemography_data = get_insight_data(
insight_id=4093,
audience_id=audience_id,
)
Ein einzelner Eintrag kann beispielsweise diese Struktur besitzen:
{
"feature": {
"id": 113143,
"display_name": "Alter von 20 bis 24 Jahren",
"display_name_category": "Alter | Erweitert"
},
"mean_pop": 0.06245027855038643,
"index_value": 333.3926086425781,
"abs_audience": 704479,
"effect_value": 0.6023614406585693,
"mean_audience": 0.20820461213588715,
"mean_audience_in_feature": 0.16638120247935742,
"options": []
}
Andere Merkmale, beispielsweise Geschlecht oder Einkommensklassen, besitzen mehrere Ausprägungen im Feld options:
{
"feature": {
"id": 674,
"display_name": "Geschlecht",
"display_name_category": "Demografie"
},
"mean_pop": 0.4823901653289795,
"index_value": 93.48028564453125,
"abs_audience": 1525796,
"effect_value": -0.06293999403715134,
"mean_audience": 0.45093968510627747,
"mean_audience_in_feature": 0.046651789240254996,
"options": [
{
"option": {
"id": 30,
"display_name": "Weiblich"
},
"mean_pop": 0.5175890326499939,
"index_value": 106.08036804199219,
"abs_audience": 1857796,
"effect_value": 0.06298159807920456,
"mean_audience": 0.5490603446960449,
"mean_audience_in_feature": 0.05293992306484044
},
{
"option": {
"id": 31,
"display_name": "Männlich"
},
"mean_pop": 0.4823901653289795,
"index_value": 93.48028564453125,
"abs_audience": 1525796,
"effect_value": -0.06293999403715134,
"mean_audience": 0.45093968510627747,
"mean_audience_in_feature": 0.046651789240254996
}
]
}
Die API unterscheidet damit zwischen einem Merkmal und seinen möglichen Ausprägungen. Ein Merkmal kann eigene Kennwerte besitzen. Zusätzliche Ausprägungen stehen im Feld options.
Der Abruf für gesellschaftliche Themen, Werte und Persönlichkeit funktioniert identisch:
values_data = get_insight_data(
insight_id=4226,
audience_id=audience_id,
)
Ein gekürzter Ausschnitt der Rückgabe kann so aussehen:
[
{
"feature": {
"id": 66877,
"display_name": "Vertraut Nachrichtenorganisationen mit einem nachweislich objektiven Ruf",
"display_name_category": "Werteorientierung | Aussagen"
},
"mean_pop": 0.1435798555612564,
"index_value": 121.83638000488281,
"abs_audience": 591900,
"effect_value": 0.40730535984039307,
"mean_audience": 0.17493250966072083,
"mean_audience_in_feature": 0.060803041962406955,
"options": []
},
{
"feature": {
"id": 68065,
"display_name": "Mag es, aufzufallen",
"display_name_category": "Lifestyle | Konsum"
},
"mean_pop": 0.09987956285476685,
"index_value": 160.50848388671875,
"abs_audience": 542441,
"effect_value": 0.7506524324417114,
"mean_audience": 0.16031518578529358,
"mean_audience_in_feature": 0.08010254646728736,
"options": []
}
]
Für eine Marketingplattform können wir zunächst die stärksten positiven und negativen Abweichungen vom Bevölkerungsdurchschnitt zeigen. Denkbar sind beispielsweise die zehn Merkmale mit den höchsten und die zehn Merkmale mit den niedrigsten Indexwerten.
Auch die Mediennutzung wird über denselben Endpunkt geladen:
media_data = get_insight_data(
insight_id=4160,
audience_id=audience_id,
)
Ein gekürzter Ausschnitt der Antwort kann so aussehen:
[
{
"feature": {
"id": 100641,
"display_name": "Nutzungsfrequenz - Podcasts: monatlich",
"display_name_category": "Medienkanal"
},
"mean_pop": 0.03581279143691063,
"index_value": 145.99864196777344,
"abs_audience": 176915,
"effect_value": 0.10836236923933029,
"mean_audience": 0.052286189049482346,
"mean_audience_in_feature": 0.07286133228038165,
"options": []
},
{
"feature": {
"id": 100642,
"display_name": "Nutzungsfrequenz - Podcasts: gar nicht",
"display_name_category": "Medienkanal"
},
"mean_pop": 0.7651251554489136,
"index_value": 94.23609161376953,
"abs_audience": 2439651,
"effect_value": -0.11763506382703781,
"mean_audience": 0.7210240364074707,
"mean_audience_in_feature": 0.04702897949476535,
"options": []
}
]
Die Struktur entspricht den vorherigen Insight-Paketen. Dadurch kann das Backend dieselbe Abruf- und Aufbereitungslogik für Soziodemografie, Werte und Mediennutzung verwenden.
Für die Darstellung sind vor allem folgende Felder relevant:
Das Feld mean_audience_in_feature wird in den API-Antworten ebenfalls mitgeliefert und in der späteren Normalisierung beibehalten. Seine fachliche Bedeutung wird in diesem Artikel nicht weiter erläutert. Vor einer Darstellung im Frontend sollte die genaue Interpretation deshalb mit der API-Dokumentation abgeglichen werden.
Der Index vergleicht die Zielgruppe mit der Bevölkerung:
Index 100 = entspricht dem Bevölkerungsdurchschnitt
Index 150 = etwa 50 % stärker vertreten
Index 70 = unterdurchschnittlich vertreten
Ein hoher Anteil allein bedeutet noch nicht, dass ein Merkmal für die Zielgruppe besonders charakteristisch ist.
Ein Beispiel: 80 Prozent einer Zielgruppe nutzen regelmäßig das Internet. Wenn der Anteil in der Gesamtbevölkerung ebenfalls 80 Prozent beträgt, liegt der Index ungefähr bei 100. Das Merkmal unterscheidet die Zielgruppe dann nicht vom Bevölkerungsdurchschnitt. Für die Reichweiten- oder Kanalplanung kann der hohe Anteil trotzdem relevant sein.
Um relevante Merkmale zu identifizieren, sollten deshalb immer Index und Anteil gemeinsam betrachtet werden. Der Anteil zeigt, wie häufig ein Merkmal in der Zielgruppe vorkommt. Der Index zeigt, wie stark sich die Zielgruppe damit vom Bevölkerungsdurchschnitt unterscheidet.
Die bisherigen Insight-Abfragen liefern fachlich vergleichbare Daten, aber nicht immer dieselbe technische Form. Einige Kennwerte stehen direkt am Merkmal. Andere stehen innerhalb der Liste options.
Wir erstellen deshalb eine Funktion, die zwei Aufgaben übernimmt:
def normalize_insight_data(data: Any) -> Any:
if not isinstance(data, list):
return data
metric_fields = (
"index_value",
"mean_pop",
"mean_audience",
"abs_audience",
"effect_value",
"mean_audience_in_feature",
)
rows: list[dict[str, Any]] = []
for feature_result in data:
feature = feature_result.get("feature") or {}
has_feature_metrics = any(
feature_result.get(field) is not None
for field in metric_fields
)
results = (
[feature_result] if has_feature_metrics else []
) + (feature_result.get("options") or [])
for result in results:
option = result.get("option") or {}
rows.append(
{
"feature_id": feature.get("id"),
"feature_name": feature.get("display_name"),
"option_id": option.get("id"),
"option_name": option.get("display_name"),
**{
field: result.get(field)
for field in metric_fields
},
}
)
return rows
Anschließend definieren wir die drei Insight-Pakete, laden ihre Daten und normalisieren die Ergebnisse:
insight_packages = {
4093: "Soziodemografie",
4226: "Werte, Gesellschaft & Persönlichkeit",
4160: "Mediennutzung",
}
insights = {
insight_id: {
"name": name,
"data": normalize_insight_data(
get_insight_data(insight_id, audience_id)
),
}
for insight_id, name in insight_packages.items()
}
Wenn wir anschließend "insights[4160]["data"][:10]" aufrufen, erhalten wir eine flache Liste. Jeder Eintrag besitzt dieselben Schlüssel, unabhängig davon, ob die Werte ursprünglich direkt am Merkmal oder innerhalb von options lagen:
[
{
"feature_id": 465,
"feature_name": "Nutzungsfrequenz - Radio: seltener",
"option_id": None,
"option_name": None,
"index_value": 93.35467529296875,
"mean_pop": 0.010170605964958668,
"mean_audience": 0.009494735859334469,
"abs_audience": 32126,
"effect_value": -0.2348584085702896,
"mean_audience_in_feature": 0.0465891032430749,
},
{
"feature_id": 466,
"feature_name": "Nutzungsfrequenz - Fernsehen: seltener",
"option_id": None,
"option_name": None,
"index_value": 117.24342346191406,
"mean_pop": 0.012939149513840675,
"mean_audience": 0.01517030131071806,
"abs_audience": 51330,
"effect_value": 0.10862775146961212,
"mean_audience_in_feature": 0.058510898649898314,
},
{
"feature_id": 1038,
"feature_name": "Nutzungsfrequenz - Regionale Zeitungen: seltener",
"option_id": None,
"option_name": None,
"index_value": 110.85298919677734,
"mean_pop": 0.008700056001543999,
"mean_audience": 0.009644272737205029,
"abs_audience": 32632,
"effect_value": 0.1638609766960144,
"mean_audience_in_feature": 0.055321726881559834,
},
{
"feature_id": 1054,
"feature_name": "Nutzungsfrequenz - Podcasts: seltener",
"option_id": None,
"option_name": None,
"index_value": 102.04902648925781,
"mean_pop": 0.01183029729872942,
"mean_audience": 0.012072702869772911,
"abs_audience": 40849,
"effect_value": 0.002879570936784148,
"mean_audience_in_feature": 0.05092806154605316,
},
{
"feature_id": 1056,
"feature_name": "Nutzungsfrequenz - TikTok: seltener",
"option_id": None,
"option_name": None,
"index_value": 120.45699310302734,
"mean_pop": 0.006634918507188559,
"mean_audience": 0.007992222905158997,
"abs_audience": 27042,
"effect_value": 0.31914934515953064,
"mean_audience_in_feature": 0.06011464513183867,
},
{
"feature_id": 1057,
"feature_name": "Nutzungsfrequenz - YouTube: seltener",
"option_id": None,
"option_name": None,
"index_value": 116.16215515136719,
"mean_pop": 0.016012422740459442,
"mean_audience": 0.018600376322865486,
"abs_audience": 62936,
"effect_value": 0.30282410979270935,
"mean_audience_in_feature": 0.05797129158732631,
},
{
"feature_id": 1183,
"feature_name": "Nutzungsfrequenz - X (ehemals Twitter): seltener",
"option_id": None,
"option_name": None,
"index_value": 92.0189208984375,
"mean_pop": 0.006589286495000124,
"mean_audience": 0.006063390523195267,
"abs_audience": 20516,
"effect_value": -0.16468152403831482,
"mean_audience_in_feature": 0.045922491540245226,
},
{
"feature_id": 1184,
"feature_name": "Nutzungsfrequenz - Instagram: seltener",
"option_id": None,
"option_name": None,
"index_value": 60.367591857910156,
"mean_pop": 0.02499515749514103,
"mean_audience": 0.015088975429534912,
"abs_audience": 51055,
"effect_value": -0.13508690893650055,
"mean_audience_in_feature": 0.030126741882256433,
},
{
"feature_id": 1186,
"feature_name": "Nutzungsfrequenz - Reddit: seltener",
"option_id": None,
"option_name": None,
"index_value": 127.88665008544922,
"mean_pop": 0.003512878669425845,
"mean_audience": 0.004492503125220537,
"abs_audience": 15201,
"effect_value": 0.30190929770469666,
"mean_audience_in_feature": 0.06382245865505207,
},
{
"feature_id": 1379,
"feature_name": "Nutzungsfrequenz - Facebook: seltener",
"option_id": None,
"option_name": None,
"index_value": 64.59850311279297,
"mean_pop": 0.028781289234757423,
"mean_audience": 0.018592283129692078,
"abs_audience": 62909,
"effect_value": -0.1280009001493454,
"mean_audience_in_feature": 0.032238199109034506,
},
]
Diese normalisierte Struktur kann das Backend direkt an das Frontend weitergeben. Das Frontend muss dann nicht mehr zwischen Kennwerten auf Merkmals- und Optionsebene unterscheiden.
Die bisherigen Beispiele zeigen den vollständigen technischen Ablauf. Für den Einsatz in einer produktiven Plattform sollten wir zusätzlich einige Punkte berücksichtigen.
Der vollständige API-Key gehört in einen Secret Store oder eine geschützte Umgebungsvariable. Er darf weder an den Browser ausgeliefert noch in Client-Code eingebaut werden.
Sowohl die Projektliste als auch die Zielgruppenliste können mehr Einträge enthalten, als die API in einer einzelnen Antwort liefert. Die Plattform sollte deshalb entweder alle Seiten abrufen oder selbst eine paginierte Oberfläche anbieten.
Weder die Zielgruppenerstellung noch jede Insight-Berechnung ist sofort abgeschlossen. Das Frontend benötigt deshalb klar definierte interne Zustände, beispielsweise:
QUEUED
CALCULATING
READY
ERROR
Diese internen Zustände können auf die verschiedenen Statuswerte der AIlon API abgebildet werden. Dadurch bleibt die Darstellung im Frontend konsistent, auch wenn Zielgruppen- und Insight-Berechnungen unterschiedliche Statusbezeichnungen verwenden.
Das Frontend sollte die Insight-Endpunkte nicht bei jedem Tabwechsel oder erneuten Rendern wieder auslösen.
Sinnvoll ist ein eigener serverseitiger Cache oder eine persistierte Ergebnisstruktur. Die Plattform lädt die Daten nur dann neu, wenn sich die Zielgruppe verändert hat, ein Ergebnis fehlt oder ausdrücklich eine Neuberechnung gestartet wurde.
Die voraussichtlichen Kosten eines Insights können vor dem eigentlichen Datenabruf geprüft werden:
GET /insights/{insight_id}/credit-cost/?audience_id={audience_id}
def get_insight_credit_cost(
insight_id: int,
audience_id: int,
) -> dict[str, Any]:
return api_request(
"GET",
f"/insights/{insight_id}/credit-cost/",
params={
"audience_id": audience_id,
},
)
Diese Information kann intern protokolliert, einem Kundenkonto zugeordnet oder vor der Analyse in der Oberfläche angezeigt werden.
In öffentlichen Beispielprojekten betragen die Insight-Kosten immer null. Reicht das Guthaben in einem eigenen Projekt nicht aus, kann die API mit 402 Payment Required antworten. Weitere Details enthält die technische Dokumentation zur AIlon API.
Besonders relevant sind folgende HTTP-Statuscodes:
Bei Insight-Anfragen können außerdem maschinenlesbare Fehlercodes wie audience_not_calculated, audience_outdated oder calculation_failed auftreten. Auch diese Fehlercodes sollten strukturiert protokolliert und ausgewertet werden.
Mit der AIlon API lässt sich der gesamte Ablauf einer Zielgruppenanalyse in bestehende Produktsysteme und eigene Plattformen integrieren. Die eigene Anwendung bleibt dabei die zentrale Oberfläche. Nutzerinnen und Nutzer können Projekte verwalten, Zielgruppen per Freitext beschreiben, Berechnungen starten und die Ergebnisse direkt im vertrauten Interface auswerten.
Das eigene Backend übernimmt die sichere Authentifizierung und die Kommunikation mit AIlon. Es lädt Projekte und Zielgruppen, überwacht asynchrone Berechnungen, ruft Potenzial, Zusammenfassung und Insights ab und bringt die Ergebnisse in eine einheitliche Struktur für das Frontend.
Für den produktiven Einsatz sind vor allem ein sicher gespeicherter API-Key, eine vollständige Pagination, klar definierte Statusmodelle, ein sinnvoller Cache, die Berücksichtigung der Credits und ein strukturiertes Fehlerprotokoll wichtig.
So entsteht eine flexible Integration, die sich an den eigenen Prozess und die eigene Benutzeroberfläche anpasst. Welche Funktionen und Insights sichtbar werden und wie die Ergebnisse präsentiert werden, bleibt vollständig in der eigenen Anwendung steuerbar.
Im AIlon Dashboard findet ihr im Home-Bereich unter „AIlon Integrationen“ die Dokumentation und euren API Key:
Falls du weitere Fragen zur API hast, schreibe uns eine Nachricht. Bis dahin frohes Ausprobieren und Integrieren!
Wo erreiche ich meine Zielgruppe? Mit AIlon in ChatGPT, Claude, MCP & Co. Medienkanäle und Werbetrigger analysieren und daraus passende Strategien...
Wie verarbeitet AIlon Datenquellen, gewichtet Signale und bildet Interessen, Affinitäten und Zielgruppenmerkmale? Die Methodik unserer...
GIM und AIlon (ERASON) verbinden Marktforschung mit KI: 'Insight-to-Impact' wandelt Marktforschung in Echtzeit in präzise Marketing- und...
Be the first to know about new B2B SaaS Marketing insights to build or refine your marketing function with the tools and knowledge of today’s industry.