Skip to content

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.