Caja de Autor Personalizable en Blogger

Caja de Autor Personalizable en NichoClean v2.0 — (gadget #config-autores)

En NichoClean v2.0 la gestión de autores se centraliza con un gadget oculto (#config-autores) y un script que inyecta la caja de autor en el sitio. El sistema está pensado para: 1) dejar un marcador vacío en la plantilla (donde el JS inyecta la caja por defecto) y 2) permitir declarar autores invitados directamente dentro del post.

1. Gadget: configuración central de autores

Añade este gadget HTML/JavaScript en el Diseñador de Blogger (Layout → Añadir gadget → HTML/JavaScript) o directamente en tu plantilla. Aquí se definen los autores, su estado (data-activo) y la opción global data-activado para encender/apagar la funcionalidad:

<!-- Gadget: Configuración Autores NichoClean -->
<!-- Opciones generales:
     - data-activado="true|false" → Mostrar autores globalmente
-->
<div id="config-autores" hidden data-activado="false">

  <!-- Autor principal -->
  <div class="autor" data-rol="principal"
       data-nombre="Juan Pérez"
       data-activo="true"
       data-avatar="https://ui-avatars.com/api/?name=Juan+Pérez&background=0077cc&color=fff"
       data-bio="Especialista en desarrollo web y diseño minimalista. Comparte recursos útiles para bloggers."
       data-perfil="https://tusitio.com/juan-perez"
       data-facebook="https://facebook.com/juan.perez"
       data-twitter="https://twitter.com/juanperez"
       data-instagram="https://instagram.com/juanperez"
       data-email="mailto:juan@example.com">
  </div>

  <!-- Autor invitado 1 -->
  <div class="autor" data-rol="invitado1"
       data-nombre="Ana López"
       data-activo="false"
       data-avatar="https://ui-avatars.com/api/?name=Ana+López&background=ff6600&color=fff"
       data-bio="Apasionada por SEO y creación de contenido optimizado para blogs."
       data-perfil="https://tusitio.com/ana-lopez"
       data-facebook=""
       data-twitter="https://twitter.com/anal"
       data-instagram=""
       data-email="">
  </div>

  <!-- Autor invitado 2 -->
  <div class="autor" data-rol="invitado2"
       data-nombre="Carlos Gómez"
       data-activo="false"
       data-avatar="https://ui-avatars.com/api/?name=Carlos+Gómez&background=00cc77&color=fff"
       data-bio="Colaborador ocasional en tutoriales de programación y diseño."
       data-perfil="https://tusitio.com/carlos-gomez"
       data-facebook="https://facebook.com/carlos.gomez"
       data-twitter=""
       data-instagram="https://instagram.com/carlosgomez"
       data-email="">
  </div>

</div>
IMPORTANTE: por defecto data-activado="false". Para activar el sistema cambia a data-activado="true".

2. Marcadores y dónde colocarlos

Hay dos conceptos de marcador y cada uno cumple un propósito distinto:

  • Marcador global en la plantilla (donde el JS inyecta la caja por defecto):
    Debe dejarse vacío en la plantilla, dentro del contenedor principal (por ejemplo debajo de <data:post.body/>). El script inyectará aquí la caja de autor por defecto (normalmente el autor principal).
    <!-- Ejemplo dentro de la plantilla (layout) -->
    <data:post.body/>
      <div class="autor-post" data-autor=""></div> <!-- DEJAR VACÍO en la plantilla para inyección automática -->
      ...
    </div>
  • Mini-marcador dentro del post para autores invitados:
    Colócalo dentro del contenido del post (dentro del scope del artículo). Sirve para declarar que ese post tiene un autor distinto (invitado). El script busca este marcador dentro del scope del post y lo prioriza.
    <!-- Ejemplo dentro del editor de la entrada -->
    <div data-autor="Ana López"></div>

3. Reglas de decisión para mostar el autor

  1. Si el gadget #config-autores no existe o data-activado esta en "false", el script oculta los marcadores y no muestra nada.
  2. Para cada marcador (.autor-post o #autor-post), el script determina el autor así:
    • Primero: busca un mini-marcador dentro del scope del post (ej. <div data-autor="Ana López">). Si existe y el autor está marcado como data-activo="true" → se usa.
    • Si el mini-marcador pide un autor que está inactivo → el marcador se oculta y no se muestra nada.
    • Si no hay mini-marcador válido, se usa el data-autor del propio marcador (.autor-post) si existe y está activo.
    • Si tampoco hay autor en el marcador, se usa el autor principal definido en el gadget (si está activo).
    • Si al final no hay autor disponible o el autor elegido está inactivo → el marcador se oculta.
  3. El script genera el HTML de la caja y además añade un <script type="application/ld+json"> (JSON-LD) por marcador para SEO.

4. script para mostar el autor

Pega este script al final de la plantilla (antes de </body>), después del gadget #config-autores:

<script>
//<![CDATA[
document.addEventListener("DOMContentLoaded", function () {

  // --------------- helpers ---------------
  function findPostScope(el) {
    // Intenta encontrar el contenedor del post (varía según plantillas)
    const scopes = ['article','.post','.post-body','.post-content','.entry','.blog-post'];
    for (const s of scopes) {
      const anc = el.closest(s);
      if (anc) return anc;
    }
    return document; // fallback global
  }

  function safeText(s){ return (s||"").trim(); }

  // --------------- obtener marcadores (soporte id o clase) ---------------
  let markers = Array.from(document.querySelectorAll('.autor-post'));
  if (markers.length === 0) {
    const byId = document.querySelector('#autor-post');
    if (byId) markers = [byId];
  }

  if (markers.length === 0) return; // no hay marcadores en la página

  // --------------- leer gadget ---------------
  const config = document.querySelector('#config-autores');
  if (!config || config.dataset.activado !== "true") {
    // ocultamos todos los marcadores
    markers.forEach(m => { m.innerHTML = ""; m.style.display = "none"; });
    return;
  }

  // construir mapa de autores desde el gadget (incluye inactivo flag)
  const autores = {};
  config.querySelectorAll('.autor').forEach(a => {
    const nombre = safeText(a.dataset.nombre);
    if (!nombre) return;
    autores[nombre] = {
      rol: a.dataset.rol || '',
      activo: a.dataset.activo === "true",
      avatar: a.dataset.avatar || '',
      bio: a.dataset.bio || '',
      perfil: a.dataset.perfil || '#',
      facebook: a.dataset.facebook || '',
      twitter: a.dataset.twitter || '',
      instagram: a.dataset.instagram || '',
      email: a.dataset.email || ''
    };
  });

  // buscar autor principal activo (fallback)
  let principalName = null;
  for (const k in autores) {
    if (autores[k].rol === 'principal' && autores[k].activo) { principalName = k; break; }
  }

  // --------------- procesar cada marcador ---------------
  markers.forEach(marker => {
    // limpiar estilos previos
    marker.style.display = ""; // reset
    marker.innerHTML = "";

    // 1) autor propuesto por el marcador mismo (#autor-post data-autor="")
    let markerDataAutor = safeText(marker.dataset.autor);

    // 2) autor propuesto desde dentro del post (mini-marcador: <div data-autor="Ana López"></div>)
    // buscarmos en el scope del post (no en todo el documento)
    const postScope = findPostScope(marker);
    let localAutorEl = null;
    if (postScope && postScope !== document) {
      localAutorEl = postScope.querySelector('[data-autor]');
      // evita coger el mismo marker si éste tuviese data-autor (marker ya tenemos)
      if (localAutorEl === marker) localAutorEl = null;
    }
    const localAutorName = localAutorEl ? safeText(localAutorEl.getAttribute('data-autor')) : "";

    // regla de decisión (siguiendo lo que pediste):
    // priorizar localAutorName (from the post small marker) if exists and active;
    // else use marker.dataset.autor if set and active;
    // else use principalName (if active);
    // if author chosen is inactive -> do NOT show anything
    let chosenName = "";
    if (localAutorName && autores[localAutorName] && autores[localAutorName].activo) {
      chosenName = localAutorName;
    } else if (localAutorName && autores[localAutorName] && !autores[localAutorName].activo) {
      // explicitly requested author is inactive -> do not show anything
      marker.style.display = 'none';
      return;
    } else if (markerDataAutor && autores[markerDataAutor] && autores[markerDataAutor].activo) {
      chosenName = markerDataAutor;
    } else if (markerDataAutor && autores[markerDataAutor] && !autores[markerDataAutor].activo) {
      // explicitly requested by marker but inactive -> hide
      marker.style.display = 'none';
      return;
    } else if (principalName) {
      chosenName = principalName;
    } else {
      // no author available
      marker.style.display = 'none';
      return;
    }

    const autor = autores[chosenName];
    if (!autor || !autor.activo) { marker.style.display = 'none'; return; }

    // --------------- construir HTML (inserta .autor-box dentro del marker) ---------------
    const redes = `
      <div class="autor-redes">
        ${autor.facebook ? `<a href="${autor.facebook}" target="_blank" rel="noopener nofollow" aria-label="Facebook"><svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M22 12a10 10 0 1 0-11.5 9.9v-7h-2v-3h2v-2.3c0-2 1.2-3.1 3-3.1.9 0 1.8.2 1.8.2v2h-1c-1 0-1.3.6-1.3 1.2V12h2.2l-.4 3H14v7A10 10 0 0 0 22 12z"/></svg></a>` : ""}
        ${autor.twitter ? `<a href="${autor.twitter}" target="_blank" rel="noopener nofollow" aria-label="Twitter"><svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M22.5 5.9c-.8.4-1.7.6-2.6.8a4.6 4.6 0 0 0 2-2.6c-.9.6-1.9 1-3 1.2a4.5 4.5 0 0 0-7.7 4.1A12.8 12.8 0 0 1 3.1 4.9a4.5 4.5 0 0 0 1.4 6A4.4 4.4 0 0 1 3 10v.1a4.5 4.5 0 0 0 3.6 4.4c-.4.1-.8.2-1.3.2-.3 0-.6 0-.9-.1a4.5 4.5 0 0 0 4.2 3.1 9 9 0 0 1-6.6 1.8A12.8 12.8 0 0 0 9.5 21c7.9 0 12.2-6.6 12.2-12.3v-.6c.8-.6 1.5-1.3 2-2.2z"/></svg></a>` : ""}
        ${autor.instagram ? `<a href="${autor.instagram}" target="_blank" rel="noopener nofollow" aria-label="Instagram"><svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M7 2C4.2 2 2 4.2 2 7v10c0 2.8 2.2 5 5 5h10c2.8 0 5-2.2 5-5V7c0-2.8-2.2-5-5-5H7zm0 2h10c1.7 0 3 1.3 3 3v10c0 1.7-1.3 3-3 3H7c-1.7 0-3-1.3-3-3V7c0-1.7 1.3-3 3-3zm5 2a5 5 0 1 0 0 10 5 5 0 0 0 0-10zm0 2a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm4.5-.5a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"/></svg></a>` : ""}
        ${autor.email ? `<a href="${autor.email}" aria-label="Correo"><svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2zm0 2v.5l8 5 8-5V6H4zm0 2.7v9.3h16V8.7l-8 5-8-5z"/></svg></a>` : ""}
      </div>
    `;

    const inner = `
      <div class="autor-box">
        <section class="autor-info" itemscope itemtype="https://schema.org/Person">
          <img src="${autor.avatar}" alt="Foto de ${chosenName}" class="autor-avatar" itemprop="image" loading="lazy">
          <div class="autor-detalles">
            <h4 class="autor-nombre" itemprop="name">${chosenName}</h4>
            <p class="autor-bio" itemprop="description">${autor.bio}</p>
            <a href="${autor.perfil}" target="_blank" rel="author nofollow" class="autor-link">Ver perfil</a>
            ${redes}
          </div>
        </section>
      </div>
    `;

    marker.innerHTML = inner;

    // JSON-LD dinámico (por marcador)
    const jsonLD = {
      "@context": "https://schema.org",
      "@type": "Person",
      "name": chosenName,
      "url": autor.perfil,
      "image": autor.avatar,
      "description": autor.bio,
      "sameAs": [
        ...(autor.facebook ? [autor.facebook] : []),
        ...(autor.twitter ? [autor.twitter] : []),
        ...(autor.instagram ? [autor.instagram] : []),
        ...(autor.email ? [autor.email] : [])
      ]
    };
    const scriptLD = document.createElement("script");
    scriptLD.type = "application/ld+json";
    scriptLD.textContent = JSON.stringify(jsonLD, null, 2);
    marker.appendChild(scriptLD);
  });

});
//]]>
</script>

5. Ejemplo práctico (paso a paso)

1) Coloca el gadget #config-autores en Layout o plantilla y actívalo: data-activado="true".

2) En la plantilla (por ejemplo debajo de <data:post.body/>) deja el marcador vacío para inyección automática:

<data:post.body/>
  <div class="autor-post" data-autor=""></div> 

3) Si quieres asignar un autor invitado a una entrada concreta, edita la entrada y pega dentro del contenido (en el editor HTML) un mini-marcador:

<div data-autor="Ana López"></div>

Resultado: si Ana López está activa en el gadget, el script detectará el mini-marcador en el scope del post y mostrará la caja de autor de Ana en lugar del autor principal. Si Ana está marcada como data-activo="false", el marcador se ocultará (evita mostrar perfiles obsoletos).

6. Añadir o editar autores (rápido)

  1. Abre el gadget #config-autores en el Diseñador o en la plantilla.
  2. Duplica uno de los <div class="autor"> y modifica data-nombre, data-bio, data-avatar, etc.
  3. Marca data-activo="true" para que el autor pueda aparecer; usa false para mantenerlo guardado pero oculto.

7. Ventajas de este plugin de autores para blogger

  • Configuración centralizada: editar autores desde un solo gadget.
  • Control de disponibilidad: puede existir un autor guardado pero inactivo (data-activo="false").
  • Prioridad de autor por post: puedes sobreescribir el autor de forma puntual dentro del post.
  • Inyección automática: deja el marcador vacío en la plantilla y el JS se encarga de todo.
  • JSON-LD por marcador: mejora la señalización para motores de búsqueda.

Esta implementación usa un gadget de configuración y una lógica de prioridad clara: mini-marcador en el post → marcador (si tiene data-autor) → autor principal. Además respeta la bandera de activación global y el flag data-activo por autor, lo que facilita gestionar colaboraciones, autores invitados y mantener el control sobre qué perfiles se muestran sin tocar cada entrada.