SEO Técnico Máximo

function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu("🔍 SEO Técnico Máximo")
    .addItem("Crear hoja de análisis", "crearHojaAnalisis")
    .addItem("Procesar URLs en lote", "procesarTodasURLs")
    .addToUi();
}

function crearHojaAnalisis() {
  const ss = SpreadsheetApp.getActive();
  let hoja = ss.getSheetByName("Análisis SEO Máximo");
  if (!hoja) hoja = ss.insertSheet("Análisis SEO Máximo");
  hoja.clear();
  hoja.appendRow([
    "URL",
    "HTTP Code", "Title", "H1",
    "Meta Description", "Canonical", "Noindex",
    "Imgs Count", "Internal Links", "External Links"
  ]);
  SpreadsheetApp.getUi().alert("🟢 Hoja 'Análisis SEO Máximo' lista.");
}

function procesarTodasURLs() {
  const hoja = SpreadsheetApp.getActive().getSheetByName("Análisis SEO Máximo");
  if (!hoja) return SpreadsheetApp.getUi().alert("Primero crea la hoja de análisis.");
  
  const urls = hoja.getRange(2,1,hoja.getLastRow()-1).getValues().flat();
  const resultados = urls.map(url => url && SEO_INFO(url));
  resultados.forEach((fila, i) => hoja.getRange(i+2,2,1,fila.length).setValues([fila]));
  
  SpreadsheetApp.getUi().alert("✅ Procesado completo.");
}

function SEO_INFO(url) {
  try {
    const html = fetchHTML(url);
    const code = fetchCode(url);
    const title = extract(html, /<title>(.*?)<\/title>/i);
    const h1 = extract(html, /<h1[^>]*>(.*?)<\/h1>/i);
    const metaDesc = extract(html, /<meta\s+name=["']description["']\s+content=["'](.*?)["']/i);
    const canonical = extract(html, /<link\s+rel=["']canonical["']\s+href=["'](.*?)["']/i);
    const noindex = /<meta\s+name=["']robots["']\s+content=["'][^"']*noindex[^"']*["']/i.test(html) ? "Sí" : "No";
    const imgsCount = (html.match(/<img\s+[^>]*>/gi) || []).length;
    const base = url.match(/https?:\/\/[^\/]+/)[0];
    const internal = countLinks(html, base, true);
    const external = countLinks(html, base, false);

    return [code, title, h1, metaDesc, canonical, noindex, imgsCount, internal, external];
  } catch (e) {
    console.error("Error en SEO_INFO:", e);
    return ["Error", "", "", "", "", "", "", "", ""];
  }
}

function fetchHTML(url) {
  return UrlFetchApp.fetch(url, { muteHttpExceptions: true }).getContentText();
}

function fetchCode(url) {
  try {
    return UrlFetchApp.fetch(url, { followRedirects: false, muteHttpExceptions: true }).getResponseCode();
  } catch {
    return "Error";
  }
}

function extract(html, regex) {
  const m = html.match(regex);
  return m?.[1]?.trim() || "";
}

function countLinks(html, base, internal=true) {
  const body = html.split(/<\/head>/i)[1]?.split(/<\/body>/i)[0] || "";
  const regex = internal
    ? /href=["']((?!http)[^"']+|http[^"']*)["']/gi
    : /href=["'](http[^"']+)["']/gi;
  const matches = Array.from(body.matchAll(regex));
  const unique = new Set(matches.map(m => {
    const link = m[1].startsWith("http")
      ? m[1]
      : (base + (m[1].startsWith("/") ? "" : "/") + m[1]);
    return internal
      ? link.startsWith(base) && link
      : !link.startsWith(base) && link;
  }).filter(Boolean));
  return unique.size;
}

¿Le ha resultado útil este artículo?