Guía de servicios · Las objeciones

Las objeciones: FAQs que convierten

El campo faqs[] del frontmatter convierte las preguntas reales del cliente en un acordeón nativo (sin JS) y emite el schema FAQPage. Una fuente, dos salidas: el componente en la ficha y el JSON-LD para Google.

Las FAQs no son marketing: son las objeciones del cliente escritas en su voz antes de que lleguen por WhatsApp. El cliente que llega al chat ya leyó el alcance, el proceso y las respuestas a sus dudas. Las conversaciones son más cortas, más precisas y cierran antes.

El FAQAccordion usa details/summary HTML nativo — sin JavaScript, accesible de teclado, indexable por crawlers aunque el acordeón esté cerrado. El mismo array faqs[] emite el schema FAQPage vía buildSchema(). Una sola fuente, ningún dato duplicado.

Definición

¿Qué es faqs[] y el FAQAccordion?

Un array de { question, answer } en el frontmatter que alimenta el acordeón de la ficha L3 y el schema FAQPage. Si viene, ambas salidas se activan; si no, se omiten.

faqs[] es un campo opcional del frontmatter de cada servicio: una lista de pares pregunta/respuesta que Zod valida en build-time. Si el array viene, la ficha L3 pinta el FAQAccordion y buildSchema() incluye el schema FAQPage en el @graph del JSON-LD. Si no viene, ninguna de las dos cosas aparece.

El FAQAccordion envuelve cada FAQ en un elemento HTML details/summary. Native browser API: sin JavaScript, sin librerías de UI. Funciona con teclado, es accesible con lectores de pantalla y los crawlers de Google pueden leer el contenido aunque el acordeón esté cerrado en la vista inicial.

Función e importancia

¿Para qué sirve?

Resuelve las objeciones del cliente antes del contacto, reduce la fricción del primer WhatsApp y cualifica el lead. Un lado extra: la semántica FAQPage es útil aunque los rich results de Google sean más restrictivos desde mayo 2026.

Las FAQs cumplen un trabajo de ventas: responden las preguntas que el cliente tiene antes de decidir si escribe por WhatsApp. «¿Atienden mi zona?» filtra por geografía. «¿Cuánto tarda?» maneja la expectativa. «¿Qué pasa si no quedo satisfecho?» resuelve el riesgo percibido. Cada FAQ bien escrita convierte un freno en una razón para seguir adelante.

El schema FAQPage que emite buildSchema() coloca las preguntas en el JSON-LD. Nota: desde mayo de 2026 Google restringió cuándo muestra FAQPage como resultado enriquecido, aunque el schema sigue siendo semánticamente correcto y la fuente única garantiza que página y schema estén siempre sincronizados.

Una fuente, dos usos

faqs[] en el frontmatter alimenta el FAQAccordion en la página y el schema FAQPage en el JSON-LD. Se escribe una vez en el .md y el sistema hace el resto. Actualizar una respuesta propaga el cambio a ambas salidas en el siguiente build.

Sin JavaScript — rendimiento y accesibilidad

FAQAccordion usa details/summary nativo: funciona sin una sola línea de JS. Accesible de teclado (Tab + Enter), indexable por Google aunque esté cerrado, compatible con lectores de pantalla sin ARIA adicional. El Core Web Vitals no se ve afectado.

Leads cualificados antes del WhatsApp

El cliente que llega al chat ya leyó el alcance, el proceso y las FAQs. Las conversaciones son más cortas y van al grano. Las objeciones escritas filtran a quien no encaja antes de que llegue por WhatsApp.

Anatomía

¿Qué lleva cada FAQ?

Dos campos: question (la objeción en voz del cliente) y answer (el dato primero). El array completo alimenta el componente y el schema desde una sola fuente.

Cada ítem del array faqs[] es un objeto con dos campos obligatorios: question y answer. Zod los valida como strings no vacíos — una pregunta sin respuesta rompe el build con mensaje claro. El orden del array es el orden de aparición en el acordeón.

Abajo, el ejemplo anotado de un servicio real. Cada punto numerado explica la decisión detrás del campo.

1

El array faqs[]

Lista de objetos { question, answer } en el frontmatter del servicio. Zod valida que question y answer sean strings no vacíos. El array es opcional; si viene, FAQAccordion y el schema FAQPage se activan solos.

Dato faqs?: { question: string, answer: string }[]

2

question — la objeción en voz del cliente

La pregunta tal como el cliente la haría por WhatsApp. Escrita en su voz («¿Atienden mi zona?»), no desde el proveedor. La pregunta correcta es la que resuelve la objeción real que frena la conversión.

Dato question: string — voz del cliente, no del proveedor

3

answer — el dato primero

La respuesta directa: primero el dato («Sí, atendemos toda la CDMX y Estado de México») y luego el matiz si aplica. Sin rodeos. Una respuesta que requiere tres párrafos para llegar al «sí» o el «no» no resuelve la objeción.

Dato answer: string — dato primero, matiz después si aplica

4

FAQAccordion — details/summary nativo

El componente que renderiza faqs[] en la ficha L3 con el elemento HTML details/summary: sin JavaScript, accesible de teclado, indexable por crawlers aunque el acordeón esté cerrado.

Dato FAQAccordion · details/summary nativo · sin JS · WCAG compliant

5

Schema FAQPage — la salida semántica

El mismo faqs[] alimenta el schema FAQPage via buildSchema(). Una fuente, dos salidas. Nota: desde mayo 2026 Google restringió los FAQPage rich results; el schema sigue siendo correcto semánticamente.

Dato @type:"FAQPage" en el JSON-LD @graph — misma fuente que el componente

Variantes

Tipos de objeción por servicio

Las FAQs más útiles responden una de cinco familias de objeción: geográfica, temporal, de precio, de confianza y de cualificación.

No hay un catálogo universal: cada servicio tiene sus propias objeciones. Pero casi todas caen en cinco familias. Identificar a cuál pertenece cada pregunta ayuda a redactar la respuesta correcta.

Abajo, seis configuraciones de faqs[] ordenadas por tipo de objeción.

  • Zona Dato primero · respuesta directa FAQAccordion + FAQPage

    Objeción geográfica

    Zona · Cobertura

    «¿Atienden mi zona?» con las zonas cubiertas y excepciones. Filtra leads fuera del área antes del chat.

  • Tiempo Dato primero · respuesta directa FAQAccordion + FAQPage

    Objeción de tiempo

    Tiempo · Plazos

    «¿Cuánto tarda?» con rango estimado. Maneja la expectativa del cliente antes del contacto.

  • Precio Dato primero · respuesta directa FAQAccordion + FAQPage

    Objeción de precio

    Precio · Cotización

    «¿Cuánto cuesta?» con el modelo de cotización honesto. Explica cómo se determina el precio sin inventar cifras.

  • Garantía Dato primero · respuesta directa FAQAccordion + FAQPage

    Objeción de confianza

    Garantía · Riesgo

    «¿Qué pasa si no quedo satisfecho?» Responde el riesgo percibido antes de comprometerse.

  • Perfil Dato primero · respuesta directa FAQAccordion + FAQPage

    Cualificación de lead

    Perfil · Filtro

    «¿Para quién es este servicio?» Filtra proactivamente a clientes que no encajan antes del WhatsApp.

  • Borrador Dato primero · respuesta directa Sin faqs[] — sección omitida

    Mínimo (sin faqs[])

    Borrador · Arranque

    faqs[] es opcional. Sin él, FAQAccordion y FAQPage se omiten. Se añade cuando se identifican las primeras objeciones reales.

Responsive y móvil

El acordeón nativo en pantallas pequeñas

details/summary es HTML nativo: funciona en móvil sin JavaScript. El único ajuste responsive es el touch target del summary (≥44px) para que el toque sea cómodo.

FAQAccordion no tiene dependencias de JS: cada pregunta es un details y el resumen es un summary. En móvil, el touch target debe ser de al menos 44px de altura (WCAG 2.5.5). El ícono de expandir/cerrar se añade con CSS puro (::after), sin ningún evento de clic en JavaScript.

En una pantalla de 375px, listar 6 respuestas completas empuja el CTA de conversión muy abajo del fold. Con details/summary, el visitante expande solo lo que le interesa y llega antes al WhatsApp.

FAQAccordion nativo en móvil

details/summary HTML puro: sin JS, touch target ≥44px, accesible. El ícono + / × se añade con CSS ::after.

CSS · touch target y control del ícono sin JS
/* FAQAccordion responsive: details/summary nativo.
   Touch target ≥44px en el summary. Ícono con CSS puro, sin JS. */
.faq-item details summary {
  padding: var(--sp-4) var(--sp-5);
  min-height: 44px;
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.faq-item details[open] summary::after { content: "×"; color: var(--c-primary); }
.faq-item details:not([open]) summary::after { content: "+"; }

Posición

¿Dónde vive?

faqs[] en el frontmatter del .md. FAQAccordion en la ficha L3 antes del cierre. buildSchema() emite FAQPage desde lib/seo.ts automáticamente.

El campo faqs[] está en el frontmatter del archivo de servicio (src/content/servicios/). El FAQAccordion va en el layout de la ficha L3, antes del cierre: el visitante lee las FAQs, resuelve sus dudas y llega al CTA de WhatsApp con la decisión más madura.

buildSchema() recibe el array desde la página y lo incluye en el JSON-LD si no está vacío. No hay que tocar lib/seo.ts para añadir FAQs: el cambio en el .md se propaga solo en el siguiente build.

Implementación

Cómo se construye

Tres piezas: faqs[] en el frontmatter, FAQAccordion condicional en la ficha L3, y la emisión del schema FAQPage desde buildSchema().

El flujo: se añade faqs[] al .md, se verifica que el layout de la ficha L3 tenga el bloque condicional con FAQAccordion, y buildSchema() hace el resto.

Abajo, las tres recetas del sistema.

frontmatter · campo faqs[] con objeciones reales
---
# src/content/servicios/instalacion-camaras.md
title: "Instalación de cámaras de seguridad IP"
description: "Diseño, instalación y configuración de sistemas de cámaras IP para
  hogar y negocio. Cobertura CDMX y Estado de México. Garantía de 12 meses."
category: "instalacion"
image: "/images/servicios/instalacion-camaras-seguridad-ip.avif"
faqs:
  - question: "¿Atienden mi zona?"
    answer: "Sí. Atendemos toda la Ciudad de México y el Estado de México. Para
      zonas fuera de esa área, escríbenos por WhatsApp para evaluar."
  - question: "¿Cuánto tarda la instalación?"
    answer: "Entre 4 y 8 horas para una instalación residencial estándar (4-8
      cámaras). Para instalaciones comerciales hacemos diagnóstico previo."
  - question: "¿Qué garantía tienen?"
    answer: "12 meses en materiales y 3 meses en mano de obra. Si algo falla
      por causas de instalación en ese periodo, regresamos sin costo adicional."
---
ServiceLayout · FAQAccordion condicional en la ficha L3
---
// src/pages/servicios/[...slug].astro — FAQAccordion condicional.
import FAQAccordion from '@components/FAQAccordion.astro'
const { entry } = Astro.props
---
{entry.data.faqs && entry.data.faqs.length > 0 && (
  <section aria-labelledby="faq-heading">
    <h2 id="faq-heading">Preguntas frecuentes</h2>
    {/* details/summary nativo: sin JS, accesible, indexable */}
    <FAQAccordion items={entry.data.faqs} />
  </section>
)}
lib/seo.ts · emisión del schema FAQPage
// lib/seo.ts — faqSchema() y su uso en buildSchema().
function faqSchema(faqs: { question: string; answer: string }[]) {
  return {
    '@type': 'FAQPage',
    mainEntity: faqs.map((f) => ({
      '@type': 'Question',
      name: f.question,
      acceptedAnswer: { '@type': 'Answer', text: f.answer },
    })),
  }
}
// buildSchema({ ..., faqs: entry.data.faqs })
// → incluye FAQPage en el @graph si el array viene y no está vacío.

El bloque condicional en el layout (entry.data.faqs && entry.data.faqs.length > 0) garantiza que FAQAccordion solo aparezca cuando hay preguntas que mostrar. Lo mismo aplica al schema: buildSchema() revisa si el array viene antes de incluir el bloque FAQPage en el @graph.

Buenas prácticas

Qué hacer y qué evitar

Las FAQs que convierten se escriben desde el cliente, responden con el dato primero y se revisan cuando las mismas preguntas siguen llegando al chat.

La diferencia entre FAQs que funcionan y FAQs que son relleno está en la perspectiva: las que funcionan son las preguntas que el cliente haría si estuviera sentado frente a ti, antes de firmar.

Abajo, los patrones concretos.

Sí conviene

  • Escribe las FAQs en voz del cliente: «¿Cuánto cuesta?» es mejor pregunta que «¿Cuál es su modelo de precios?». La objeción real es la del cliente.
  • Responde con el dato primero. «Sí, atendemos CDMX y Estado de México» es una respuesta; «Dependiendo de varios factores…» no lo es.
  • Limita faqs[] a 5-8 preguntas por servicio: las que realmente llegan por WhatsApp, no las imaginadas.
  • Revisa las FAQs cada trimestre: si las mismas preguntas siguen llegando al chat, las respuestas no son lo suficientemente claras.
  • Para FAQs que aplican a todos los servicios, considera una página /preguntas-frecuentes global que complemente las específicas de cada ficha.

Mejor evita

  • NO pongas preguntas que nadie hace. Las FAQs son para resolver objeciones reales, no para parecer exhaustivo.
  • NO dejes respuestas vagas. «Depende del proyecto» sin especificar de qué depende no resuelve nada. Si varía, da el rango: «Entre 3 y 10 días hábiles».
  • NO dupliques en las FAQs el contenido ya explicado en el alcance o el proceso. Cada sección cumple su función.
  • NO uses faqs[] como sección de marketing. «¿Por qué son los mejores?» con respuesta elogiosa no es una FAQ.
  • NO olvides actualizar las FAQs cuando cambia el servicio. Un precio o zona desactualizados en una FAQ rompen la confianza.
¿Necesitas ayuda?