feat: al conectar Google, auto-emparejar Drive/GA4/GSC/Ads en fichas
Bootstrap unificado post-OAuth + botón Emparejar todo. Meta discover también intenta FB/IG pages con el token system user (API 4V2030). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -54,40 +54,36 @@ export default function GoogleOrganicPanel() {
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (params.get('drive') === 'ok') {
|
||||
const boot = params.get('boot');
|
||||
setMsg(
|
||||
'Google reconectado. Pulsa «Descubrir y emparejar» para GA4/GSC.'
|
||||
boot
|
||||
? `Google reconectado · ${boot}`
|
||||
: 'Google reconectado. Emparejando fichas…'
|
||||
);
|
||||
}
|
||||
void loadStatus();
|
||||
}, []);
|
||||
|
||||
async function discover(apply: boolean) {
|
||||
async function bootstrapAll() {
|
||||
setBusy('match');
|
||||
setErr(null);
|
||||
const res = await fetch('/api/admin/google/organic', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'match', apply }),
|
||||
body: JSON.stringify({ action: 'bootstrap', days: 28 }),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) {
|
||||
setBusy(null);
|
||||
setErr(data.error || 'Discover falló');
|
||||
setBusy(null);
|
||||
if (!res.ok && !data.message) {
|
||||
setErr(data.error || 'Emparejado falló');
|
||||
return;
|
||||
}
|
||||
setMatches(data.matches || []);
|
||||
setGa4Count(data.ga4Count || 0);
|
||||
setGscCount(data.gscCount || 0);
|
||||
setMsg(
|
||||
apply
|
||||
? `Emparejado · GA4 ${data.applied?.ga4 || 0} · GSC ${data.applied?.gsc || 0}. Actualizando datos…`
|
||||
: `Vistas ${data.ga4Count} props GA4 · ${data.gscCount} sites GSC (sin escribir)`
|
||||
);
|
||||
if (apply) {
|
||||
await syncAll();
|
||||
} else {
|
||||
setBusy(null);
|
||||
setMsg(data.message || 'Emparejado listo');
|
||||
if (data.organic) {
|
||||
setGa4Count(data.organic.ga4Visible || 0);
|
||||
setGscCount(data.organic.gscVisible || 0);
|
||||
}
|
||||
await loadStatus();
|
||||
}
|
||||
|
||||
async function syncAll() {
|
||||
@@ -109,7 +105,7 @@ export default function GoogleOrganicPanel() {
|
||||
0
|
||||
);
|
||||
setMsg(
|
||||
`Datos al día · ${data.synced || 0} clientes · ${wrote} días en Orgánico (se actualiza solo al abrir la vista y cada noche)`
|
||||
`Datos al día · ${data.synced || 0} clientes · ${wrote} días en Orgánico`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -128,12 +124,12 @@ export default function GoogleOrganicPanel() {
|
||||
<Leaf className="w-5 h-5 text-lime-600 mt-0.5 shrink-0" />
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-gray-900">
|
||||
2 · Orgánico (GA4 + Search Console)
|
||||
2 · Orgánico + emparejado Google
|
||||
</h3>
|
||||
<p className="text-xs text-gray-600 mt-0.5 max-w-xl">
|
||||
No es otra cuenta: usa la conexión del panel 1. Aquí solo
|
||||
emparejas propiedades/sites a cada cliente y actualizas datos.
|
||||
Luego se mantienen al día solos.
|
||||
Al conectar Google (panel 1) se rellenan solos Drive, GA4, GSC y
|
||||
Google Ads en cada ficha. Aquí puedes repetir el emparejado y
|
||||
actualizar Orgánico.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -141,7 +137,7 @@ export default function GoogleOrganicPanel() {
|
||||
<button
|
||||
type="button"
|
||||
disabled={!connected || busy !== null}
|
||||
onClick={() => void discover(true)}
|
||||
onClick={() => void bootstrapAll()}
|
||||
className="inline-flex items-center gap-1.5 text-xs font-semibold px-3 py-1.5 rounded-lg border border-gray-200 text-gray-800 hover:bg-gray-50 disabled:opacity-40"
|
||||
>
|
||||
{busy === 'match' ? (
|
||||
@@ -149,7 +145,7 @@ export default function GoogleOrganicPanel() {
|
||||
) : (
|
||||
<Search className="w-3.5 h-3.5" />
|
||||
)}
|
||||
Descubrir y emparejar
|
||||
Emparejar todo Google
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user