perf: creatividades warehouse-first + aviso OAuth Ads Production
Carga métricas desde ad_daily al instante (mode=fast) y enriquece previews en vivo; la UI de Agencia avisa si falta scope Ads o consent Testing. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -552,39 +552,70 @@ export default function AdTrackerClient({
|
||||
async function load() {
|
||||
setCreativesLoading(true);
|
||||
setCreativesWarning(null);
|
||||
const platform = tab === 'meta' ? 'meta' : 'google';
|
||||
const baseQs = {
|
||||
since: range.since,
|
||||
until: range.until,
|
||||
platform,
|
||||
};
|
||||
|
||||
let hasFast = false;
|
||||
|
||||
// 1) Warehouse first — instant metrics (source of truth from sync)
|
||||
try {
|
||||
const platform = tab === 'meta' ? 'meta' : 'google';
|
||||
const qs = new URLSearchParams({
|
||||
since: range.since,
|
||||
until: range.until,
|
||||
platform,
|
||||
const qs = new URLSearchParams({ ...baseQs, mode: 'fast' });
|
||||
const r = await fetch(`/api/ad-tracker/creatives?${qs}`, {
|
||||
cache: 'no-store',
|
||||
});
|
||||
const data = await r.json().catch(() => ({}));
|
||||
if (cancelled) return;
|
||||
if (r.ok) {
|
||||
hasFast = true;
|
||||
setCreatives((data.ads as AdCreativeCard[]) || []);
|
||||
if (
|
||||
data.metaClickSplit &&
|
||||
typeof data.metaClickSplit.clicks === 'number'
|
||||
) {
|
||||
setMetaClickSplit(data.metaClickSplit);
|
||||
} else if (platform === 'google') {
|
||||
setMetaClickSplit(null);
|
||||
}
|
||||
setCreativesLoading(false);
|
||||
}
|
||||
} catch {
|
||||
/* continue to live */
|
||||
}
|
||||
|
||||
// 2) Live enrich (previews) — never blocks empty UI
|
||||
try {
|
||||
const qs = new URLSearchParams({ ...baseQs, mode: 'live' });
|
||||
const r = await fetch(`/api/ad-tracker/creatives?${qs}`, {
|
||||
cache: 'no-store',
|
||||
});
|
||||
const data = await r.json().catch(() => ({}));
|
||||
if (cancelled) return;
|
||||
if (!r.ok) {
|
||||
setCreatives([]);
|
||||
setMetaClickSplit(null);
|
||||
setCreativesWarning(data.hint || data.error || 'No se pudieron cargar creatividades');
|
||||
if (!hasFast) {
|
||||
setCreativesWarning(
|
||||
data.hint || data.error || 'No se pudieron cargar creatividades'
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
setCreatives((data.ads as AdCreativeCard[]) || []);
|
||||
const liveAds = (data.ads as AdCreativeCard[]) || [];
|
||||
if (liveAds.length) setCreatives(liveAds);
|
||||
if (
|
||||
data.metaClickSplit &&
|
||||
typeof data.metaClickSplit.clicks === 'number'
|
||||
) {
|
||||
setMetaClickSplit(data.metaClickSplit);
|
||||
} else if (platform === 'google') {
|
||||
setMetaClickSplit(null);
|
||||
}
|
||||
const w = Array.isArray(data.warnings) ? data.warnings.filter(Boolean) : [];
|
||||
const w = Array.isArray(data.warnings)
|
||||
? data.warnings.filter(Boolean)
|
||||
: [];
|
||||
setCreativesWarning(w.length ? w.join(' · ') : null);
|
||||
} catch {
|
||||
if (!cancelled) {
|
||||
setCreatives([]);
|
||||
setMetaClickSplit(null);
|
||||
if (!cancelled && !hasFast) {
|
||||
setCreativesWarning('Error al cargar creatividades');
|
||||
}
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user