The most important input to any AI marketing decision is who you're marketing to. Our research shows that audience persona is the single highest-leverage variable in creative scoring — a targeted persona improves prediction accuracy by 8-12 percentage points over a generic one.
This guide covers how to use Kettio's Audiences API to automatically discover target audience segments, build structured demographic personas, and use them across scoring and testing workflows.
Why Audience Matters More Than Anything Else
We ran hundreds of experiments comparing different variables in our scoring pipeline. Model choice, prompt engineering, temperature settings, anchor calibration — all of these matter, but none of them move the needle as much as getting the audience right.
Here's why: an ad that's perfect for budget-conscious parents is terrible for luxury-seeking millennials. An ad that stops Gen Z from scrolling makes Gen X cringe. The same creative can score a 4.5 for one audience and a 2.1 for another.
No brand runs ads targeting "everyone." Your AI agent shouldn't either.
Automatic Audience Discovery
Don't know who the target audience is? Give Kettio a brand URL and it will figure it out.
How It Works
The POST /api/audiences/research endpoint:
- Scrapes the brand's website to understand their products, positioning, and price points
- Analyzes the brand voice, visual style, and product categories
- Infers up to 3 distinct audience segments with full demographics
- Returns structured data you can pass directly to the Rank API
Example: Discovering Audiences from a Brand URL
curl -X POST https://kettio.com/api/audiences/research -H "Authorization: Bearer agk_live_YOUR_KEY" -H "Content-Type: application/json" -d '{
"url": "https://allbirds.com"
}'
Response:
{
"segments": [
{
"name": "Eco-conscious urban professionals",
"demographics": {
"ageRange": "25-34",
"incomeLevel": "75k-100k",
"priceSensitivity": "moderate",
"adSkepticism": "high",
"trustBaseline": "moderate",
"categoryFamiliarity": "knowledgeable",
"shoppingIntent": "researching",
"brandFamiliarity": "heard-of",
"platformFatigue": "high"
}
},
{
"name": "Comfort-first active lifestyle buyers",
"demographics": {
"ageRange": "35-44",
"incomeLevel": "100k-150k",
"priceSensitivity": "low",
"adSkepticism": "moderate",
"trustBaseline": "high",
"categoryFamiliarity": "casual",
"shoppingIntent": "browsing",
"brandFamiliarity": "familiar",
"platformFatigue": "medium"
}
},
{
"name": "Sustainability-driven Gen Z shoppers",
"demographics": {
"ageRange": "18-24",
"incomeLevel": "25k-50k",
"priceSensitivity": "high",
"adSkepticism": "very-high",
"trustBaseline": "low",
"categoryFamiliarity": "knowledgeable",
"shoppingIntent": "comparing",
"brandFamiliarity": "familiar",
"platformFatigue": "very-high"
}
}
]
}
Notice how different these segments are. The Gen Z segment has very-high ad skepticism, very-high platform fatigue, and high price sensitivity. The active lifestyle segment is the opposite — low price sensitivity, moderate skepticism, and medium platform fatigue. Ads that work for one audience will fail for the other.
Creating and Saving Audiences
Once you have audience data — either from research or your own knowledge — save it for reuse across scoring calls:
// Create a saved audience
const createRes = await fetch('https://kettio.com/api/audiences', {
method: 'POST',
headers: {
'Authorization': 'Bearer agk_live_YOUR_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Eco-conscious urban professionals',
description: 'Sustainability-minded 25-34 year olds in urban areas, mid-to-high income, researching before buying',
industry: 'sustainable fashion',
seedKeywords: ['eco-friendly', 'sustainable', 'ethical fashion', 'comfort'],
demographics: {
ageRange: '25-34',
incomeLevel: '75k-100k',
priceSensitivity: 'moderate',
adSkepticism: 'high',
shoppingIntent: 'researching',
platformFatigue: 'high'
}
})
});
const { audience } = await createRes.json();
console.log('Saved audience ID:', audience.id);
// Now use it in scoring calls
const rankRes = await fetch('https://kettio.com/api/v1/rank', {
method: 'POST',
headers: {
'Authorization': 'Bearer agk_live_YOUR_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
assets: [{ url: 'https://cdn.example.com/ad.png', id: 'ad-1' }],
audience_id: audience.id,
goal: 'purchase-intent'
})
});
Managing Audiences
The full CRUD API for audiences:
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/audiences |
List all saved audiences |
POST |
/api/audiences |
Create a new audience |
GET |
/api/audiences/:id |
Get a single audience |
PUT |
/api/audiences/:id |
Update an audience (partial) |
DELETE |
/api/audiences/:id |
Delete an audience |
Full Agent Workflow: Research → Create → Score
Here's a complete workflow an AI marketing agent would follow when starting with a brand it knows nothing about:
async function evaluateBrandCreatives(apiKey, brandUrl, adUrls) {
// Step 1: Research the brand to discover audience segments
const researchRes = await fetch('https://kettio.com/api/audiences/research', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ url: brandUrl })
});
const { segments } = await researchRes.json();
// Step 2: Save the primary segment for reuse
const createRes = await fetch('https://kettio.com/api/audiences', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: segments[0].name,
demographics: segments[0].demographics
})
});
const { audience } = await createRes.json();
// Step 3: Score creatives against each discovered segment
const scoringResults = await Promise.all(
segments.map(segment =>
fetch('https://kettio.com/api/v1/rank', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
assets: adUrls.map((url, i) => ({ url, id: `ad-${i}` })),
audience: {
name: segment.name,
demographics: segment.demographics
},
goal: 'purchase-intent'
})
}).then(r => r.json())
)
);
// Step 4: Find universal winners (high scores across all segments)
const assetScores = {};
for (const result of scoringResults) {
for (const asset of result.ranked) {
if (!assetScores[asset.asset_id]) assetScores[asset.asset_id] = [];
assetScores[asset.asset_id].push(asset.score);
}
}
const universalRanking = Object.entries(assetScores)
.map(([id, scores]) => ({
id,
avgScore: scores.reduce((a, b) => a + b, 0) / scores.length,
minScore: Math.min(...scores),
maxScore: Math.max(...scores)
}))
.sort((a, b) => b.avgScore - a.avgScore);
return { segments, audience, universalRanking };
}
This pattern — research, save, score across segments, find universal winners — is what separates a basic scoring call from an intelligent agent workflow. The agent isn't just scoring; it's building understanding of the brand's audience landscape and finding creatives that work broadly.
Audience Design Best Practices
Be Specific About Ad Skepticism
This is the most underrated demographic field. A Gen Z audience with very-high ad skepticism will punish anything that feels like a traditional ad. A boomer audience with low skepticism responds well to direct promotional messaging. Getting this wrong produces misleading scores.
Match Platform Fatigue to Channel
If you're scoring Instagram feed ads, your audience likely has high or very-high platform fatigue — they see hundreds of ads daily. For email headers, fatigue is lower. For billboard images, it's not a factor. Match the fatigue level to where the ad will actually appear.
Set Shopping Intent Correctly
An audience that's browsing responds to inspiration and discovery. An audience that's ready-to-buy responds to clear pricing, urgency, and product details. The same ad scores very differently depending on where the audience is in their buying journey.
Use Research as a Starting Point
The /api/audiences/research endpoint gives you a strong starting point, but you know your actual customers better than a scraper does. Use the research segments as a foundation, then adjust demographics based on your real customer data.
Build Smarter Audiences
Start with AI-discovered segments, then refine with your customer data. Your scores are only as good as your audience.
Get Started Free →Frequently Asked Questions
How does audience research work?
Kettio scrapes the brand URL to understand products, pricing, brand voice, and visual identity. It then uses AI to infer the most likely customer segments with structured demographic data. The entire process takes about 10-15 seconds.
Can I create audiences without using the research endpoint?
Absolutely. If you already know your target demographics, use POST /api/audiences directly with your own data. The research endpoint is a convenience for when you don't have audience data yet.
How many audiences can I save?
There's no hard limit on saved audiences. Create as many as you need for different products, campaigns, or market segments.
Do different audiences cost different credit amounts?
No. Audience creation and research are free. Credits are only used when you score creatives via the Rank API. Each scored asset costs 1 credit regardless of audience complexity.
Can I use audiences across different evaluation goals?
Yes. A saved audience can be used with any evaluation goal. The audience defines who is evaluating; the goal defines what they're evaluating for. You might score the same audience's response to an ad for both scroll-stopping and purchase-intent.
