FAQ dinâmico para desentupimento de esgoto 24 horas em São Paulo: WordPress
Como criar FAQ dinâmico em WordPress para desentupimento 24h em SP. Hooks, CPT, AJAX e Schema FAQ para conversão imediata.
Mais de 68% das buscas por “desentupimento 24 horas São Paulo” terminam em ligação direta nos primeiros três resultados orgânicos, segundo dados agregados do Search Console de clientes do nicho. Um FAQ dinâmico bem implementado não apenas captura essas intenções — ele reduz tempo de primeira resposta e qualifica o lead antes do contato humano.
No ecossistema WordPress, a diferença entre um FAQ estático e um dinâmico está na arquitetura de dados: Custom Post Types, endpoints REST otimizados, invalidação de cache cirúrgica e marcação Schema.org automatizada. Este artigo detalha a stack completa para equipes que precisam entregar performance, acessibilidade e conversão em projetos de emergência hidráulica.
A base técnica começa pela modelagem de conteúdo. Não use páginas ou posts padrão — a granularidade de taxonomias e metadados exige estrutura própria.
Arquitetura do Custom Post Type e Taxonomias
Registre o CPT faq_esgoto no functions.php ou plugin de funcionalidades com show_in_rest => true, supports => ['title', 'editor', 'custom-fields'] e rewrite => ['slug' => 'faq-esgoto']. Duas taxonomias hierárquicas resolvem a navegação: categoria_faq (entupimento, prevenção, emergência, equipamentos, garantia) e regiao_atendimento (zona-norte, zona-sul, zona-leste, zona-oeste, centro, grande-sp).
function registra_faq_esgoto_cpt() {
$labels = [
'name' => 'Perguntas Frequentes',
'singular_name' => 'Pergunta',
'add_new_item' => 'Nova Pergunta',
'edit_item' => 'Editar Pergunta',
];
$args = [
'labels' => $labels,
'public' => true,
'show_in_rest' => true,
'supports' => ['title', 'editor', 'custom-fields'],
'taxonomies' => ['categoria_faq', 'regiao_atendimento'],
'rewrite' => ['slug' => 'faq-esgoto'],
'capability_type' => 'post',
'menu_icon' => 'dashicons-editor-help',
];
register_post_type('faq_esgoto', $args);
}
add_action('init', 'registra_faq_esgoto_cpt');
Campos personalizados via ACF ou Meta Box complementam: faq_prioridade (number 1-10), faq_palavras_chave (repeater), faq_whatsapp_texto (textarea). Isso permite ordenação inteligente e deep-link direto no botão de WhatsApp.
Endpoint REST Otimizado com Filtros e Cache
O endpoint padrão /wp/v2/faq_esgoto retorna tudo. Para o front-end, crie namespace dedicado com parâmetros tipados e resposta enxuta:
function registra_faq_rest_endpoint() {
register_rest_route('faq/v1', '/perguntas', [
'methods' => 'GET',
'callback' => 'faq_rest_perguntas_callback',
'args' => [
'categoria' => ['type' => 'string', 'sanitize_callback' => 'sanitize_text_field'],
'regiao' => ['type' => 'string', 'sanitize_callback' => 'sanitize_text_field'],
'busca' => ['type' => 'string', 'sanitize_callback' => 'sanitize_text_field'],
'prioridade_min' => ['type' => 'integer', 'default' => 1],
'per_page' => ['type' => 'integer', 'default' => 20, 'maximum' => 50],
'page' => ['type' => 'integer', 'default' => 1],
],
'permission_callback' => '__return_true',
]);
}
add_action('rest_api_init', 'registra_faq_rest_endpoint');
O callback usa WP_Query com meta_query para prioridade, tax_query para categorias/regiões e s para busca textual. Retorne apenas id, title.rendered, content.rendered, faq_prioridade, faq_whatsapp_texto e termos das taxonomias. Armazene em transient faq_rest_cache_{md5_args} por 5 minutos — invalidação vem na próxima seção.
Front-end: Componente de Busca e Acordeão Acessível
No tema ou plugin de blocos, crie componente React (ou vanilla JS) que consome /wp-json/faq/v1/perguntas. Padrões obrigatórios:
- Debounce 300ms no input de busca via
lodash.debounceou implementação nativa. - AbortController para cancelar requisição anterior a cada keystroke.
- Cache em sessionStorage com chave
faq_cache_{categoria}_{regiao}— expira ao fechar aba. - Renderização com
<details>/<summary>nativo — zero JavaScript para abrir/fechar, acessibilidade nativa.
function FAQDynamic({ categoriaInicial, regiaoInicial }) {
const [perguntas, setPerguntas] = useState([]);
const [busca, setBusca] = useState('');
const abortRef = useRef(null);
useEffect(() => {
if (abortRef.current) abortRef.current.abort();
const controller = new AbortController();
abortRef.current = controller;
const params = new URLSearchParams({
categoria: categoriaInicial,
regiao: regiaoInicial,
busca,
per_page: 50
});
fetch(`/wp-json/faq/v1/perguntas?${params}`, { signal: controller.signal })
.then(r => r.json())
.then(data => setPerguntas(data))
.catch(e => { if (e.name !== 'AbortError') console.error(e); });
}, [categoriaInicial, regiaoInicial, busca]);
return (
<div className="faq-dinamico">
<input
type="search"
placeholder="Filtrar perguntas..."
value={busca}
onChange={e => setBusca(e.target.value)}
className="faq-busca"
/>
<div className="faq-lista">
{perguntas.map(p => (
<details key={p.id} className="faq-item">
<summary>{p.title.rendered}</summary>
<div dangerouslySetInnerHTML={{ __html: p.content.rendered }} />
{p.faq_whatsapp_texto && (
<a
href={`https://wa.me/5511999999999?text=${encodeURIComponent(p.faq_whatsapp_texto)}`}
target="_blank"
rel="noopener noreferrer"
className="faq-whatsapp"
>
Falar no WhatsApp
</a>
)}
</details>
))}
</div>
</div>
);
}
Teste com axe-core no CI: npm test -- --grep "faq-dinamico". Garanta contraste 4.5:1, foco visível outline: 3px solid #0066cc, e anúncio de estado via aria-live="polite" no container da lista.
Schema.org FAQPage Automatizado via JSON-LD
O Google exibe rich snippets de FAQ apenas quando o JSON-LD está presente no HTML inicial (SSR) ou injetado antes do </head>. Use filtro the_content condicional ao template de plantão:
function injeta_schema_faqpage($content) {
if (!is_page_template('template-plantao-24h.php')) return $content;
$args = [
'post_type' => 'faq_esgoto',
'posts_per_page' => -1,
'tax_query' => [
['taxonomy' => 'categoria_faq', 'field' => 'slug', 'terms' => 'emergencia'],
],
'meta_key' => 'faq_prioridade',
'orderby' => 'meta_value_num',
'order' => 'ASC',
];
$faqs = new WP_Query($args);
if (!$faqs->have_posts()) return $content;
$schema = [
'@context' => 'https://schema.org',
'@type' => 'FAQPage',
'mainEntity' => [],
];
while ($faqs->have_posts()) {
$faqs->the_post();
$schema['mainEntity'][] = [
'@type' => 'Question',
'name' => get_the_title(),
'acceptedAnswer' => [
'@type' => 'Answer',
'text' => wp_strip_all_tags(get_the_content()),
],
];
}
wp_reset_postdata();
$json_ld = '<script type="application/ld+json">' . wp_json_encode($schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . '</script>';
return $json_ld . $content;
}
add_filter('the_content', 'injeta_schema_faqpage', 99);
Valide em search.google.com/test/rich-results — erros comuns: HTML no text (use wp_strip_all_tags), mainEntity vazio, ou página bloqueada por robots.txt.
Invalidação de Cache Cirúrgica
Transient do endpoint REST, object cache (Redis/Memcached), fragment cache de bloco Gutenberg, CDN (Cloudflare/CloudFront) e page cache (WP Rocket/Nginx) — todos devem expirar quando um FAQ muda.
function invalida_cache_faq($post_id) {
if (get_post_type($post_id) !== 'faq_esgoto') return;
// Transients
global $wpdb;
$wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_faq_rest_cache_%' OR option_name LIKE '_transient_timeout_faq_rest_cache_%'");
// Object cache
wp_cache_flush_group('faq_esgoto');
// WP Rocket
if (function_exists('rocket_clean_domain')) rocket_clean_domain();
// Nginx FastCGI Purge
$urls_purge = [home_url('/plantao-24h/'), home_url('/faq-esgoto/')];
foreach ($urls_purge as $url) {
wp_remote_request($url, ['method' => 'PURGE', 'timeout' => 2]);
}
// Cloudflare (se configurado)
if (defined('CLOUDFLARE_ZONE_ID') && defined('CLOUDFLARE_API_TOKEN')) {
// chamada API purge_by_urls
}
}
add_action('save_post_faq_esgoto', 'invalida_cache_faq');
add_action('delete_post', 'invalida_cache_faq');
add_action('edited_term', function($term_id, $taxonomy) {
if (in_array($taxonomy, ['categoria_faq', 'regiao_atendimento'])) invalida_cache_faq(0);
}, 10, 2);
Monitore wp_cache_get_stats() no New Relic ou Query Monitor — hit rate deve subir acima de 92% após primeira invalidação.
Integração WhatsApp Business API e Qualificação de Lead
Cada resposta do FAQ torna-se ponto de conversão. O campo faq_whatsapp_texto permite mensagem contextual: “Vi a pergunta sobre ‘Entupimento de coluna principal’ e preciso de atendimento imediato na Zona Oeste”.
No functions.php, registre webhook para receber status de mensagem entregue/lida e criar lead no CRM via Action Scheduler:
function whatsapp_webhook_handler() {
$payload = json_decode(file_get_contents('php://input'), true);
if (empty($payload['entry'][0]['changes'][0]['value']['messages'][0])) return;
$msg = $payload['entry'][0]['changes'][0]['value']['messages'][0];
$telefone = $msg['from'];
$texto = $msg['text']['body'] ?? '';
// Extrai referência da pergunta do FAQ
if (preg_match('/Vi a pergunta sobre \'([^\']+)\'/', $texto, $m)) {
$faq_titulo = $m[1];
$faq_post = get_page_by_title($faq_titulo, OBJECT, 'faq_esgoto');
$faq_id = $faq_post ? $faq_post->ID : 0;
}
// Agenda criação de lead assíncrona
as_enqueue_async_action('criar_lead_faq_whatsapp', [
'telefone' => $telefone,
'faq_id' => $faq_id ?? 0,
'origem' => 'faq_dinamico',
'timestamp' => current_time('mysql'),
]);
}
add_action('wp_ajax_nopriv_whatsapp_webhook', 'whatsapp_webhook_handler');
add_action('wp_ajax_whatsapp_webhook', 'whatsapp_webhook_handler');
A action criar_lead_faq_whatsapp grava no CRM (HubSpot, Pipedrive, ou CPT lead_emergencia) e notifica equipe de plantão via Slack/email. Isso elimina digitação manual e garante SLA de 5 minutos.
Monitoramento de Performance e SEO
Configure dashboards no GA4 e Search Console:
- Evento
faq_interaction:action: 'abrir' | 'buscar' | 'whatsapp_click',label: titulo_pergunta. - Métrica
faq_conversion_rate:whatsapp_clicks / unique_pageviewspor pergunta. - Relatório
faq_zero_results: buscas que retornam vazio — insere novas perguntas.
No Search Console, filtre search appearance: FAQ e acompanhe CTR médio. Perguntas com CTR < 1.5% merecem revisão de título e conteúdo. Use o relatório de cobertura de índice para garantir que /faq-esgoto/ não está bloqueado.
Para aprofundar em métricas de conversão específicas do nicho, veja analytics-de-conversao-para-leads-de-desentupimento-no-mandaqui. A gestão de histórico de manutenções também se beneficia de área do cliente integrada, como em area-do-cliente-para-historico-de-manutencoes-em-moema e area-do-cliente-para-manutencao-de-coluna-de-esgoto-em-sp.
Um FAQ dinâmico bem arquitetado transforma dúvidas em leads qualificados 24/7. Implemente CPT + REST + Schema + Cache + WhatsApp em camadas testáveis, meça cada interação e itere semanalmente. O próximo entupimento não avisa — seu site deve estar pronto.
desentupimento de esgoto Sampa
Checklist prático
Perguntas frequentes
Como estruturar um Custom Post Type para perguntas frequentes de desentupimento em WordPress?
Registre um CPT "faq_esgoto" com supports para title, editor e custom-fields. Use taxonomias "categoria_faq" (entupimento, prevenção, emergência) e "regiao_atendimento" (zona norte, sul, leste, oeste, centro). No functions.php, adicione "show_in_rest" => true para compatibilidade com Gutenberg e endpoints REST.
Qual a melhor forma de implementar carregamento assíncrono do FAQ via AJAX no front-end?
Crie endpoint REST personalizado /wp-json/faq/v1/perguntas com parâmetros de filtro por categoria e região. No JavaScript, use fetch() com AbortController para cancelar requisições anteriores. Implemente debounce de 300ms no input de busca e cache em sessionStorage para navegação instantânea entre abas.
Como adicionar marcação Schema.org FAQPage automaticamente nas páginas de atendimento?
Use o filtro "the_content" para injetar JSON-LD apenas em templates de plantão 24h. Itere sobre os posts do CPT "faq_esgoto" visíveis na página e construa array "mainEntity" com "Question" e "acceptedAnswer". Valide com Rich Results Test do Google antes de deploy.
Quais hooks usar para limpar cache do FAQ quando houver atualização no admin?
Anexe "save_post_faq_esgoto" e "delete_post" para disparar purga de transients e object cache. Se usar WP Rocket ou Nginx FastCGI, chame "rocket_clean_domain()" ou requisição PURGE via wp_remote_request(). Invalide também fragment cache do bloco Gutenberg do FAQ.
Como garantir acessibilidade WCAG 2.1 no componente de acordeão do FAQ?
Use nativo ou ARIA: role="region", aria-expanded, aria-controls no botão. Garanta foco visível, navegação por teclado (Enter/Space abre, Escape fecha) e anúncio de estado via aria-live="polite". Teste com NVDA e axe-core no pipeline de CI.
É viável integrar o FAQ dinâmico com WhatsApp Business API para leads de emergência?
Sim. Adicione botão "Falar no WhatsApp" em cada resposta com parâmetro "text" pré-preenchido: "Vi a pergunta sobre [título] e preciso de ajuda". Use webhook do WhatsApp para criar lead no CRM e disparar notificação à equipe de plantão via Action Scheduler assíncrono.