fix: Meta Ads muestra clics todos y clics enlace (y ambos CPC)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user