fix: Meta Ads muestra clics todos y clics enlace (y ambos CPC)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
4Ventures
2026-09-29 01:51:45 +02:00
parent ed2afff556
commit 9270584934
6 changed files with 150 additions and 18 deletions

View File

@@ -2,7 +2,7 @@
import React, { useEffect, useMemo, useState } from 'react';
import { normalizePlatform } from '@/lib/ad-tracker-range';
import { AdDailyRow, formatEur, formatEurCents, formatNum } from '@/lib/metrics';
import { AdDailyRow, formatEur, formatEurCents, formatNum, linkClicksOf } from '@/lib/metrics';
import type { AdCreativeCard } from '@/lib/ad-creatives-meta';
import {
CreativesGallery,
@@ -527,6 +527,11 @@ export default function AdTrackerClient({
const [creatives, setCreatives] = useState<AdCreativeCard[]>([]);
const [creativesLoading, setCreativesLoading] = useState(false);
const [creativesWarning, setCreativesWarning] = useState<string | null>(null);
const [metaClickSplit, setMetaClickSplit] = useState<{
clicks: number;
linkClicks: number;
spend: number;
} | null>(null);
const [zoomAd, setZoomAd] = useState<AdCreativeCard | null>(null);
const range = useMemo(() => ({ since, until, label: rangeLabel }), [
@@ -540,6 +545,7 @@ export default function AdTrackerClient({
setCreatives([]);
setCreativesWarning(null);
setCreativesLoading(false);
setMetaClickSplit(null);
return;
}
let cancelled = false;
@@ -560,15 +566,25 @@ export default function AdTrackerClient({
if (cancelled) return;
if (!r.ok) {
setCreatives([]);
setMetaClickSplit(null);
setCreativesWarning(data.hint || data.error || 'No se pudieron cargar creatividades');
return;
}
setCreatives((data.ads as AdCreativeCard[]) || []);
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) : [];
setCreativesWarning(w.length ? w.join(' · ') : null);
} catch {
if (!cancelled) {
setCreatives([]);
setMetaClickSplit(null);
setCreativesWarning('Error al cargar creatividades');
}
} finally {
@@ -605,6 +621,22 @@ export default function AdTrackerClient({
ads: meta.ads + google.ads,
});
// Meta: clics todos (warehouse) + clics enlace (live Ads Manager o warehouse).
const metaClicksAll = metaClickSplit?.clicks ?? meta.clicks;
const metaLinkFromWarehouse = [...metaRows, ...otherRows].reduce(
(a, r) => a + linkClicksOf(r),
0
);
const metaClicksLink =
metaClickSplit?.linkClicks ??
(metaLinkFromWarehouse > 0 ? metaLinkFromWarehouse : meta.clicks);
const metaCpcAll =
metaClicksAll > 0 ? (metaClickSplit?.spend ?? meta.spend) / metaClicksAll : null;
const metaCpcLink =
metaClicksLink > 0
? (metaClickSplit?.spend ?? meta.spend) / metaClicksLink
: null;
const daily = buildSeries(filtered);
const metaCampaigns = byCampaign([...metaRows, ...otherRows]);
const googleCampaigns = byCampaign(googleRows);
@@ -674,7 +706,7 @@ export default function AdTrackerClient({
label="Impresiones"
value={formatNum(combined.impressions)}
/>
<KpiTile label="Clics (enlace)" value={formatNum(combined.clicks)} />
<KpiTile label="Clics" value={formatNum(combined.clicks)} />
<KpiTile
label="Conversiones"
value={formatNum(combined.conversions)}
@@ -836,18 +868,30 @@ export default function AdTrackerClient({
label="Impresiones"
value={formatNum(meta.impressions)}
/>
<KpiTile label="Clics (enlace)" value={formatNum(meta.clicks)} />
<KpiTile label="Clics (todos)" value={formatNum(metaClicksAll)} />
<KpiTile
label="Clics (enlace)"
value={formatNum(metaClicksLink)}
/>
<KpiTile
label="Conversiones"
value={formatNum(meta.conversions)}
/>
<KpiTile
label="CTR"
value={meta.ctr != null ? `${meta.ctr.toFixed(2)}%` : '—'}
value={
meta.impressions > 0
? `${((100 * metaClicksAll) / meta.impressions).toFixed(2)}%`
: '—'
}
/>
<KpiTile
label="CPC"
value={meta.cpc != null ? formatEurCents(meta.cpc) : '—'}
label="CPC (todos)"
value={metaCpcAll != null ? formatEurCents(metaCpcAll) : '—'}
/>
<KpiTile
label="CPC (enlace)"
value={metaCpcLink != null ? formatEurCents(metaCpcLink) : '—'}
/>
<KpiTile
label="CPL"