Files
justvitamin/scripts/generate-source-pricing-references.ts
Omair Saleh 056c47581f feat: editorial review dashboard + elite-grade pilot batch (5 SKUs)
Ships the second dashboard surface — a Pattern Library + Preview Theatre — that
presents the 4-section PDP pilot batch back to Umar, compliance, and the board
in an editorial format. Adds the full data layer that drives it: 5 source-backed
per-SKU drafts at QA 100/100, 15 competitor PDP semantic extracts, PubMed
evidence packs, EFSA claims library extension, JV brand voice guide, hand-curated
product FAQs, and the Matrixify-ready CSV exports for Lewis.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 18:50:09 +08:00

121 lines
5.5 KiB
TypeScript

#!/usr/bin/env bun
import { mkdirSync, writeFileSync } from 'fs'
import { join } from 'path'
const root = process.cwd()
const outRoot = join(root, 'content_population_exports')
mkdirSync(outRoot, { recursive: true })
function csv(rows: any[], headers: string[]) {
const esc = (value: any) => {
if (value === undefined || value === null) value = ''
if (Array.isArray(value)) value = value.join(' | ')
value = String(value)
return /[",\n\r]/.test(value) ? `"${value.replace(/"/g, '""')}"` : value
}
return [headers.join(','), ...rows.map(row => headers.map(header => esc(row[header])).join(','))].join('\n') + '\n'
}
const generatedAt = new Date().toISOString()
const rows = [
{
Provider: 'DataForSEO',
Stage: '1',
PricingItem: 'Amazon Reviews API standard queue',
Unit: 'every 10 reviews',
Price: '$0.00075',
SourceUrl: 'https://dataforseo.com/apis/reviews-api/amazon-reviews-api',
SourceCheckedAt: generatedAt,
AppliesToPlan: 'Stage 1 uses depth=10 per ASIN, so the first 9-ASIN pilot should be estimated from 9 units of 10 reviews before any buffer.',
Caveat: 'Official page uses USD pricing. Convert/record the working budget currency in data/sources/budgets/source-acquisition-cost-plan.json before approvals.'
},
{
Provider: 'DataForSEO',
Stage: '1',
PricingItem: 'Amazon Reviews API priority queue',
Unit: 'every 10 reviews',
Price: '$0.0015',
SourceUrl: 'https://dataforseo.com/apis/reviews-api/amazon-reviews-api',
SourceCheckedAt: generatedAt,
AppliesToPlan: 'Priority queue is not the default pilot recommendation; use only if turnaround time matters more than cost.',
Caveat: 'Keep the pilot in standard queue unless a human explicitly updates the cost plan and approval.'
},
{
Provider: 'DataForSEO',
Stage: '1',
PricingItem: 'Depth billing rule',
Unit: '10-review increments',
Price: 'round depth up to the next 10-review block',
SourceUrl: 'https://dataforseo.com/help-center/get-amazon-reviews',
SourceCheckedAt: generatedAt,
AppliesToPlan: 'Depth=10 avoids accidental double billing; depth=11 would be charged as 20 reviews.',
Caveat: 'Do not change depth from 10 in asin-map.csv without updating the cost plan and approval cap.'
},
{
Provider: 'Apify',
Stage: '2',
PricingItem: 'Actor compute units on Creator/standard public pricing reference',
Unit: 'compute unit',
Price: '$0.2 per CU',
SourceUrl: 'https://apify.com/pricing/creator-plan',
SourceCheckedAt: generatedAt,
AppliesToPlan: 'Stage 2 must stay one actor run, first 3 targets, 3 requests per brand, then dataset inspection.',
Caveat: 'Actor-specific runs can also incur proxy/data/storage usage; inspect actual run usage before any second run.'
},
{
Provider: 'Apify',
Stage: '2',
PricingItem: 'Actor usage drivers',
Unit: 'memory x duration plus platform services',
Price: 'varies by CU, transfer, proxy, storage',
SourceUrl: 'https://docs.apify.com/platform/actors/running/usage-and-resources',
SourceCheckedAt: generatedAt,
AppliesToPlan: 'Browser actors and heavy pages cost more; Stage 2 should use Apify only for named gaps after DataForSEO review.',
Caveat: 'Use the first dataset run as the real cost sample; do not estimate full-catalogue scraping from generic CU pricing.'
}
]
const manifest = {
generatedAt,
ready: true,
note: 'Official pricing references for filling source-acquisition-cost-plan.json. This report does not unlock spend; budget, cost-plan, approval, preflight, and spend gates still control paid usage.',
counts: {
references: rows.length,
providers: [...new Set(rows.map(row => row.Provider))].length,
dataforseoReferences: rows.filter(row => row.Provider === 'DataForSEO').length,
apifyReferences: rows.filter(row => row.Provider === 'Apify').length
},
guardrails: [
'Record current provider pricing source and timestamp before enabling budget caps.',
'Keep DataForSEO Stage 1 at depth=10 and 9 ASINs until raw quality and actual cost are reviewed.',
'Keep Apify Stage 2 behind a DataForSEO review decision and named gap.',
'This reference report is not a substitute for checking account billing pages before spend.'
],
references: rows
}
writeFileSync(join(outRoot, 'source_acquisition_pricing_references.json'), JSON.stringify(manifest, null, 2) + '\n', 'utf8')
writeFileSync(join(outRoot, 'source_acquisition_pricing_references.csv'), csv(rows, ['Provider', 'Stage', 'PricingItem', 'Unit', 'Price', 'SourceUrl', 'SourceCheckedAt', 'AppliesToPlan', 'Caveat']), 'utf8')
writeFileSync(join(outRoot, 'source_acquisition_pricing_references.md'), [
'# Source acquisition pricing references',
'',
`Generated: ${generatedAt}`,
'',
manifest.note,
'',
'## Guardrails',
...manifest.guardrails.map(item => `- ${item}`),
'',
'## References',
...rows.map(row => `- ${row.Provider} Stage ${row.Stage}: ${row.PricingItem}${row.Price} per ${row.Unit}. Source: ${row.SourceUrl}. Caveat: ${row.Caveat}`),
'',
'## How to use this',
'- Copy the relevant source URL, checked timestamp, unit cost, and estimated total into `data/sources/budgets/source-acquisition-cost-plan.json`.',
'- Then rerun `bun run source:cost-plan`, `bun run source:approvals`, and `bun run source:spend-gate`.',
'- Do not run provider APIs just because this reference file exists.',
''
].join('\n'), 'utf8')
console.log(`Source acquisition pricing references ready: ${manifest.ready}`)
console.log(`References: ${manifest.counts.references}`)