Scenario
Expanding into new markets requires localized messaging. Perigon’s geographic filtering returns news by country, state, or city. This job pulls news from target markets, creates personas representing local consumer segments, runs a Focus Group to test messaging, then generates localized campaign copy. Flow: PerigonGET /all?country={code} → Mavera POST /personas → POST /focus-groups → POST /generations → Localized copy
Code
import os, requests, time
PG_KEY = os.environ["PERIGON_API_KEY"]
PG_BASE = "https://api.goperigon.com/v1"
MV = os.environ["MAVERA_API_KEY"]
MV_BASE = "https://app.mavera.io/api/v1"
MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}
PRODUCT = "digital payments platform"
MARKETS = [
{"country": "GB", "label": "United Kingdom", "currency": "GBP"},
{"country": "DE", "label": "Germany", "currency": "EUR"},
{"country": "JP", "label": "Japan", "currency": "JPY"},
]
for market in MARKETS:
# 1. Fetch local news
r = requests.get(f"{PG_BASE}/all", params={
"apiKey": PG_KEY, "q": PRODUCT, "country": market["country"],
"sortBy": "date", "size": 10,
})
if not r.ok:
print(f"{market['label']}: API error {r.status_code}")
continue
articles = r.json().get("articles", [])
print(f"\n{market['label']}: {len(articles)} articles")
local_context = "\n".join(
f"- [{a.get('source',{}).get('name','')}] {a.get('title','')}: {a.get('summary', a.get('description',''))[:200]}"
for a in articles[:8]
)
# 2. Create local personas
LOCAL_PERSONAS = [
{"name": f"{market['label']} Early Adopter", "desc": f"Tech-forward consumer in {market['label']}. Uses multiple fintech apps. Price-sensitive but values UX. Local payment habits."},
{"name": f"{market['label']} Traditional Buyer", "desc": f"Established professional in {market['label']}. Prefers banks. Skeptical of fintech. Values security and regulation compliance."},
{"name": f"{market['label']} Small Business Owner", "desc": f"SMB owner in {market['label']}. Needs payment processing, invoicing, cross-border. Cost is primary concern."},
]
persona_ids = []
for lp in LOCAL_PERSONAS:
p = requests.post(f"{MV_BASE}/personas", headers=MV_H, json={
"name": lp["name"], "description": lp["desc"],
}).json()
persona_ids.append(p["id"])
time.sleep(0.3)
# 3. Focus Group with local context
fg = requests.post(f"{MV_BASE}/focus-groups", headers=MV_H, json={
"name": f"Market Entry: {market['label']}",
"persona_ids": persona_ids,
"questions": [
f"What matters most when choosing a {PRODUCT} in {market['label']}?",
f"What local alternatives do you currently use and why?",
f"What would make you switch to a new {PRODUCT}?",
f"How important is that the platform operates in {market['currency']}?",
],
"responses_per_persona": 2,
}).json()
for _ in range(20):
time.sleep(5)
data = requests.get(f"{MV_BASE}/focus-groups/{fg['id']}", headers=MV_H).json()
if data.get("status") == "completed":
break
# 4. Generate localized copy
fg_summary = "\n".join(
f"[{r.get('persona_id','')}] {r.get('question','')[:60]} → {r.get('answer','')[:200]}"
for r in data.get("responses", [])[:12]
)
copy = requests.post(f"{MV_BASE}/generations", headers=MV_H, json={
"prompt": f"Generate localized marketing copy for {PRODUCT} entering {market['label']}.\n\n"
f"LOCAL NEWS CONTEXT:\n{local_context}\n\n"
f"FOCUS GROUP INSIGHTS:\n{fg_summary}\n\n"
"Generate:\n"
f"1. Hero headline (8 words max) — resonates with {market['label']} values\n"
"2. Subheadline (20 words) — addresses top local concern\n"
"3. Three feature bullets — localized benefits, not features\n"
"4. CTA button text (4 words)\n"
f"5. Social proof line referencing {market['label']} adoption\n\n"
f"Currency: {market['currency']}. Tone: trustworthy, local, modern.",
}).json()
print(f"\n{'='*60}\nLOCALIZED COPY: {market['label']}\n{'='*60}")
print(copy.get("output", copy.get("content", ""))[:600])
const PG_KEY = process.env.PERIGON_API_KEY;
const PG_BASE = "https://api.goperigon.com/v1";
const MV = process.env.MAVERA_API_KEY;
const MV_BASE = "https://app.mavera.io/api/v1";
const MV_H = { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" };
const PRODUCT = "digital payments platform";
const MARKETS = [
{ country: "GB", label: "United Kingdom", currency: "GBP" },
{ country: "DE", label: "Germany", currency: "EUR" },
{ country: "JP", label: "Japan", currency: "JPY" },
];
for (const market of MARKETS) {
// 1. Local news
const r = await fetch(
`${PG_BASE}/all?apiKey=${PG_KEY}&q=${encodeURIComponent(PRODUCT)}&country=${market.country}&sortBy=date&size=10`);
if (!r.ok) { console.log(`${market.label}: error ${r.status}`); continue; }
const articles = (await r.json()).articles || [];
console.log(`\n${market.label}: ${articles.length} articles`);
const localContext = articles.slice(0, 8).map(a =>
`- [${a.source?.name||""}] ${a.title||""}: ${(a.summary||a.description||"").slice(0,200)}`).join("\n");
// 2. Local personas
const personaIds = [];
for (const lp of [
{ name: `${market.label} Early Adopter`, desc: `Tech-forward in ${market.label}. Multiple fintech apps. Price-sensitive.` },
{ name: `${market.label} Traditional Buyer`, desc: `Established in ${market.label}. Prefers banks. Values security.` },
{ name: `${market.label} SMB Owner`, desc: `SMB in ${market.label}. Payment processing, invoicing, cross-border.` },
]) {
const p = await fetch(`${MV_BASE}/personas`, { method: "POST", headers: MV_H,
body: JSON.stringify({ name: lp.name, description: lp.desc }),
}).then(r => r.json());
personaIds.push(p.id);
await new Promise(r => setTimeout(r, 300));
}
// 3. Focus Group
const fg = await fetch(`${MV_BASE}/focus-groups`, { method: "POST", headers: MV_H,
body: JSON.stringify({ name: `Market Entry: ${market.label}`, persona_ids: personaIds,
questions: [`What matters most for ${PRODUCT} in ${market.label}?`, `Local alternatives?`,
`What makes you switch?`, `How important is ${market.currency} support?`],
responses_per_persona: 2 }),
}).then(r => r.json());
let data;
for (let i = 0; i < 20; i++) {
await new Promise(r => setTimeout(r, 5000));
data = await fetch(`${MV_BASE}/focus-groups/${fg.id}`, { headers: MV_H }).then(r => r.json());
if (data.status === "completed") break;
}
const fgSummary = (data.responses || []).slice(0, 12)
.map(r => `${(r.question||"").slice(0,60)} → ${(r.answer||"").slice(0,200)}`).join("\n");
// 4. Localized copy
const copy = await fetch(`${MV_BASE}/generations`, { method: "POST", headers: MV_H,
body: JSON.stringify({ prompt: `Localized copy for ${PRODUCT} in ${market.label}.\n\nNEWS:\n${localContext}\n\nFOCUS GROUP:\n${fgSummary}\n\n1. Hero headline (8 words)\n2. Subheadline (20 words)\n3. Three feature bullets\n4. CTA (4 words)\n5. Social proof for ${market.label}\n\nCurrency: ${market.currency}. Tone: trustworthy, local.` }),
}).then(r => r.json());
console.log(`\n${"=".repeat(60)}\nLOCALIZED COPY: ${market.label}\n${"=".repeat(60)}`);
console.log((copy.output || copy.content || "").slice(0, 600));
}
Example Output
United Kingdom: 10 articles
LOCALIZED COPY: United Kingdom
============================================================
1. HEADLINE: Payments That Move at London Speed
2. SUBHEADLINE: FCA-regulated, instant GBP settlements, and the integrations
UK businesses actually use.
3. FEATURES:
• Faster Payments rails — settle in seconds, not days
• Open Banking ready — connect your high-street bank directly
• HMRC-compatible invoicing built in
4. CTA: Start Free in GBP
5. SOCIAL PROOF: Trusted by 2,400 UK businesses from Bristol to Edinburgh.
LOCALIZED COPY: Germany
============================================================
1. HEADLINE: Zahlungen, Die Einfach Funktionieren
2. SUBHEADLINE: BaFin-konform, SEPA-Sofortüberweisung, und die Integrationen
die deutsche Unternehmen tatsächlich nutzen.
Error Handling
Sparse markets
Sparse markets
Some country codes return few results. Broaden the query or remove
sourceGroup filter. For APAC markets, try region instead of country.Currency localization
Currency localization
Generated copy may default to USD. Explicitly include the target currency in the prompt and add
"Do NOT mention USD" if needed.Focus Group polling
Focus Group polling
Focus groups are async. The polling loop waits up to 100 seconds. Increase for complex multi-persona groups.