Appearance
Integration Examples
Practical JavaScript snippets covering the most common integration patterns.
1. Fetch content for the latest completed report
js
const latest = await api.get('/projects/42/reports/latest');
if (latest.data.status !== 'completed') {
console.log('Report not ready yet');
return;
}
const content = await api.get(
`/projects/42/reports/${latest.data.report_number}/content`
);
for (const keyword of content.data.keywords) {
if (!keyword.has_content) continue;
// Use keyword.content and keyword.html based on content_scheme
const scheme = content.data.content_scheme;
console.log(scheme, keyword.content);
}2. Batch sync - all content for this month across all active projects
js
let page = 1;
const allProjects = [];
// Collect all pages
while (true) {
const res = await api.get(`/projects?status=active&page=${page}`);
allProjects.push(...res.data);
if (page >= res.meta.last_page) break;
page++;
}
for (const project of allProjects) {
const latest = await api.get(`/projects/${project.id}/reports/latest`);
if (latest.data.status !== 'completed') continue;
const content = await api.get(
`/projects/${project.id}/reports/${latest.data.report_number}/content`
);
for (const keyword of content.data.keywords) {
if (!keyword.has_content) continue;
// Pick first variant for array schemes, use directly for object schemes
const variant = Array.isArray(keyword.content)
? keyword.content[0]
: keyword.content;
await cms.updatePage(keyword.keyword_url, variant);
}
}3. Publish meta tags for all keywords in a report
js
// Report 2 uses the `metadata` scheme - content is an array of 3 paired sets
const content = await api.get('/projects/42/reports/2/content');
for (const keyword of content.data.keywords) {
if (!keyword.has_content) continue;
const chosen = keyword.content[0]; // pick first variant
await cms.setMeta(keyword.keyword_url, {
title: chosen.meta_title,
description: chosen.meta_description,
});
}4. Embed ready-to-use HTML
For heading+text schemes the html field contains a pre-rendered fragment you can embed directly:
js
// content_scheme = "h2_text_blocks" → html key is "h2_and_text"
for (const keyword of content.data.keywords) {
if (!keyword.has_content) continue;
const html = keyword.html[0].h2_and_text;
// "<h2>Why choose us</h2>\n<p>We help businesses…</p>"
await cms.insertBlock(keyword.keyword_url, html);
}Refer to the scheme reference table for the exact HTML key for each scheme.
5. Find keywords that have never received content
js
const keywords = await api.get('/projects/42/keywords');
const noContent = keywords.data.filter(k => k.content_count === 0);
console.log(`${noContent.length} keywords have no content yet`);6. Check which keywords are missing content for a specific report
js
const content = await api.get('/projects/42/reports/14/content');
const missing = content.data.keywords.filter(k => !k.has_content);
console.log(`${missing.length} of ${content.data.summary.keyword_count} keywords have no content`);Sync strategy
Stable sync key: use report_number (scoped to a project) to identify which report you last synced. report_id is the internal ID if you need a globally unique reference.
Detecting new reports: compare latest_report_number or latest_report_id from GET /projects against the last value you synced. If it has increased, a new report is ready to fetch.
Content stability: once status is completed, report content is generally stable. Minor corrections may occasionally occur, but you can treat a completed report as ready to publish.