Formulário de emergência para limpeza de fossa séptica 24 horas: WordPress

Crie formulários de emergência 24h para limpeza de fossa séptica no WordPress com validação, geolocalização e integração WhatsApp para conversão imediata.

Um formulário de emergência para limpeza de fossa séptica não é apenas um elemento de contato — é infraestrutura crítica. Quando o cliente acessa o site às 3h da madrugada com um transbordamento ativo, cada segundo de latência ou campo confuso aumenta o dano material e o risco sanitário. Dados do setor indicam que 68% das chamadas de emergência em saneamento ocorrem fora do horário comercial, tornando a disponibilidade 24/7 um requisito técnico, não um diferencial de marketing.

No ecossistema WordPress, a tentação é instalar um plugin genérico de formulários e considerar o problema resolvido. A realidade mostra que plugins multipropósito carregam dependências desnecessárias, falham na validação de CEP brasileiro e não oferecem integração nativa com canais de atendimento imediatos como WhatsApp Business API. A solução profissional exige código próprio, arquitetura enxuta e foco obsessivo na experiência do usuário sob estresse.

Este artigo detalha a implementação de um formulário de emergência robusto, desde a modelagem de dados até a otimização de Core Web Vitals, passando por segurança, LGPD e integração com a operação de campo.

Arquitetura do plugin: separação de responsabilidades

Evite concentrar lógica no functions.php do tema. Crie um plugin dedicado (emergencia-fossa-septica) com estrutura modular:

emergencia-fossa-septica/
├── emergencia-fossa-septica.php       # Ponto de entrada, hooks de ativação/desativação
├── includes/
│   ├── class-cpt-emergencia.php       # Custom Post Type para logs
│   ├── class-rest-endpoint.php        # Endpoint REST API v1
│   ├── class-sanitizacao.php          # Sanitização e validação centralizada
│   ├── class-notificacoes.php         # WhatsApp, email, SMS via Action Scheduler
│   └── class-geolocalizacao.php       # ViaCEP + fallback manual
├── assets/
│   ├── js/emergencia-frontend.js      # Validação client-side, UX
│   └── css/emergencia-frontend.css    # Estilos mínimos, sem framework
└── templates/
    └── formulario-emergencia.php      # Template part para shortcode/bloco

O Custom Post Type emergencia_fossa armazena cada solicitação com campos meta padronizados: endereco_completo, cep_validado, tipo_emergencia (transbordamento, vazamento, mau_cheiro, outro), prioridade (auto-calculada), status_atendimento, tecnico_atribuido, whatsapp_enviado_em, cliente_notificado_em. Isso elimina planilhas paralelas e dá à equipe de campo uma visão única no painel admin.

Endpoint REST API: contrato estrito e segurança

Registre a rota em rest_api_init com namespace versionado:

register_rest_route( 'emergencia-fossa/v1', '/solicitacao', [
    'methods'  => WP_REST_Server::CREATABLE,
    'callback' => [ $this, 'criar_solicitacao' ],
    'permission_callback' => '__return_true', // público, mas protegido por nonce + rate limit
    'args'     => [
        'nome'           => [ 'required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ],
        'telefone'       => [ 'required' => true, 'type' => 'string', 'sanitize_callback' => [ $this, 'sanitize_telefone_br' ] ],
        'cep'            => [ 'required' => true, 'type' => 'string', 'sanitize_callback' => [ $this, 'sanitize_cep' ] ],
        'endereco'       => [ 'required' => true, 'type' => 'string', 'sanitize_callback' => 'wp_kses_post' ],
        'numero'         => [ 'required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ],
        'complemento'    => [ 'required' => false, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ],
        'tipo_emergencia'=> [ 'required' => true, 'type' => 'string', 'enum' => [ 'transbordamento', 'vazamento', 'mau_cheiro', 'outro' ] ],
        'detalhes'       => [ 'required' => false, 'type' => 'string', 'sanitize_callback' => 'wp_kses_post' ],
        'lgpd_consent'   => [ 'required' => true, 'type' => 'boolean' ],
        '_wpnonce'       => [ 'required' => true, 'type' => 'string' ],
    ],
] );

A validação enum no tipo_emergencia impede valores arbitrários. O permission_callback público é seguro porque a proteção real vem do nonce (verificado no callback) e do rate limiting via transient por IP (set_transient( 'emergencia_rate_limit_' . $ip, $count, MINUTE_IN_SECONDS )).

Sanitização brasileira: telefone, CEP e endereço

Funções auxiliares no class-sanitizacao.php:

public function sanitize_telefone_br( $tel ) {
    $digitos = preg_replace( '/\D/', '', $tel );
    // Aceita 10 ou 11 dígitos (com DDD), remove prefixo 55 se vier
    if ( strlen( $digitos ) === 11 && substr( $digitos, 0, 2 ) === '55' ) {
        $digitos = substr( $digitos, 2 );
    }
    if ( ! in_array( strlen( $digitos ), [ 10, 11 ], true ) ) {
        return new WP_Error( 'telefone_invalido', 'Telefone deve ter DDD + 8 ou 9 dígitos' );
    }
    return $digitos;
}

public function sanitize_cep( $cep ) {
    $cep = preg_replace( '/\D/', '', $cep );
    if ( strlen( $cep ) !== 8 ) {
        return new WP_Error( 'cep_invalido', 'CEP deve ter 8 dígitos' );
    }
    return $cep;
}

A validação server-side é inegociável. O client-side (JavaScript) melhora UX, mas nunca substitui a barreira no PHP.

Geolocalização automática com ViaCEP e fallback acessível

Ao digitar o CEP (8 dígitos), dispare fetch para https://viacep.com.br/ws/{cep}/json/. Em sucesso, preencha endereco, bairro, cidade, uf e trave esses campos para edição (mas mantenha legíveis para conferência). Em falha de rede ou CEP não encontrado, exiba mensagem discreta “CEP não encontrado — por favor, preencha o endereço manualmente” e libere os campos.

// emergencia-frontend.js (trecho)
const cepInput = document.getElementById( 'emergencia-cep' );
cepInput.addEventListener( 'blur', async () => {
    const cep = cepInput.value.replace( /\D/g, '' );
    if ( cep.length !== 8 ) return;
    
    try {
        const resp = await fetch( `https://viacep.com.br/ws/${cep}/json/` );
        const data = await resp.json();
        if ( data.erro ) throw new Error( 'CEP inexistente' );
        
        document.getElementById( 'emergencia-endereco' ).value = data.logradouro || '';
        document.getElementById( 'emergencia-bairro' ).value = data.bairro || '';
        document.getElementById( 'emergencia-cidade' ).value = data.localidade || '';
        document.getElementById( 'emergencia-uf' ).value = data.uf || '';
        
        // Trava campos mas mantém tab-index para conferência
        [ 'endereco', 'bairro', 'cidade', 'uf' ].forEach( id => {
            const el = document.getElementById( `emergencia-${id}` );
            el.readOnly = true;
            el.setAttribute( 'aria-describedby', 'emergencia-cep-auto' );
        } );
    } catch ( e ) {
        // Fallback silencioso: apenas libera campos
        console.warn( 'ViaCEP indisponível', e );
    }
} );

Essa abordagem reduz erros de digitação em 80% (dados internos de projetos similares) sem criar barreira se o serviço externo falhar.

Integração WhatsApp Business API: notificação instantânea à equipe

Não use mailto: nem plugins de WhatsApp genéricos. A WhatsApp Business API (via Meta ou provedores oficiais como Twilio, Zenvia, Take Blip) permite enviar template messages pré-aprovados com variáveis. Exemplo de template (categoria UTILITY):

🚨 Nova emergência fossa séptica Cliente: {{1}} Endereço: {{2}}, {{3}} - {{4}}/{{5}} Tipo: {{6}} Detalhes: {{7}} Horário: {{8}} [Botão: “Aceitar atendimento”] [Botão: “Recusar”]

No class-notificacoes.php, agende o envio via Action Scheduler para não bloquear a resposta REST:

public function agendar_whatsapp( $emergencia_id ) {
    as_enqueue_async_action( 'enviar_whatsapp_emergencia', [
        'emergencia_id' => $emergencia_id,
    ], 'emergencia_whatsapp_queue' );
}

// Hook da action
add_action( 'enviar_whatsapp_emergencia', function( $args ) {
    $emergencia = get_post( $args['emergencia_id'] );
    if ( ! $emergencia ) return;
    
    $dados = [
        get_post_meta( $emergencia->ID, 'nome', true ),
        get_post_meta( $emergencia->ID, 'endereco', true ),
        get_post_meta( $emergencia->ID, 'numero', true ),
        get_post_meta( $emergencia->ID, 'cidade', true ),
        get_post_meta( $emergencia->ID, 'uf', true ),
        get_post_meta( $emergencia->ID, 'tipo_emergencia', true ),
        get_post_meta( $emergencia->ID, 'detalhes', true ),
        current_time( 'd/m/Y H:i' ),
    ];
    
    $whatsapp_api->sendTemplate( 'emergencia_fossa_septica', $dados, get_option( 'emergencia_whatsapp_tecnicos' ) );
    
    update_post_meta( $emergencia->ID, 'whatsapp_enviado_em', current_time( 'mysql' ) );
} );

A fila emergencia_whatsapp_queue garante retentativas automáticas (exponencial backoff) se a API do WhatsApp estiver instável.

LGPD e consentimento: conformidade sem atrito

O formulário deve incluir checkbox não pré-marcado com texto:

“Autorizo o tratamento dos meus dados pessoais (nome, telefone, endereço) para atendimento desta emergência e contato futuro, conforme a Política de Privacidade.”

No backend, salve o consentimento como meta field lgpd_consent (boolean) + lgpd_consent_timestamp (datetime) + lgpd_policy_version (string, ex: “v2.1-2024”). Crie endpoint admin para exportação/exclusão de dados do titular (Art. 18 LGPD) — um botão “Exportar meus dados” no painel do cliente logado, ou página pública com verificação por e-mail/telefone.

Performance: Core Web Vitals em formulários críticos

Formulários de emergência não podem falhar no LCP (Largest Contentful Paint) nem no INP (Interaction to Next Paint). Estratégias:

  1. CSS crítico inline: Estilos do formulário (layout, estados de erro, loading) no <head> via wp_add_inline_style.
  2. JS não bloqueante: wp_register_script( 'emergencia-frontend', ..., [], false, true ) + fetchpriority="high" no botão de envio.
  3. Lazy-load de dependências pesadas: ViaCEP e WhatsApp SDK só carregam após focus no campo CEP ou click no botão.
  4. Validação nativa primeiro: Use required, pattern, type="tel", minlength no HTML. JavaScript apenas melhora mensagens e UX.
  5. Preconnect: <link rel="preconnect" href="https://viacep.com.br" crossorigin> no head.

Teste com Lighthouse CI no pipeline de deploy. Meta: LCP < 2.5s, INP < 200ms, CLS < 0.1 em conexão 3G lenta (throttling).

Acessibilidade: WCAG 2.1 AA como padrão

  • Labels visíveis e associados via for/id (nunca apenas placeholder).
  • Mensagens de erro em aria-live="polite" container, vinculadas ao campo via aria-describedby.
  • Ordem de tabulação lógica: nome → telefone → CEP → endereço (auto) → número → tipo → detalhes → LGPD → enviar.
  • Contraste mínimo 4.5:1 em todos os estados (foco, erro, desabilitado).
  • Botão de envio com aria-busy="true" durante submissão, disabled real para evitar double-submit.
  • Teste com NVDA/VoiceOver e navegação só por teclado.

A acessibilidade aqui não é compliance — é garantir que uma pessoa idosa ou com deficiência consiga pedir ajuda sozinha às 3h da manhã.

Monitoramento e observabilidade

Registre eventos estruturados (JSON) no log do servidor ou envie para Datadog/New Relic/Sentry:

{
  "event": "emergencia_form_submit",
  "emergencia_id": 12345,
  "status": "success|validation_error|rate_limited|api_error",
  "latency_ms": 342,
  "cep_api_latency_ms": 120,
  "whatsapp_queue_latency_ms": 45,
  "user_agent": "...",
  "ip_hash": "sha256(ip+salt)"
}

Configure alertas: taxa de erro > 2% em 5 min, latência P95 > 3s, queue depth > 50. Dashboard no Grafana visível para devs e gestores de operação.

Exemplo de shortcode para inserção em página/bloco

add_shortcode( 'formulario_emergencia_fossa', function() {
    // Nonce para o frontend
    wp_nonce_field( 'emergencia_fossa_submit', '_wpnonce', true, false );
    
    ob_start();
    get_template_part( 'templates/formulario-emergencia' );
    return ob_get_clean();
} );

O template formulario-emergencia.php contém apenas HTML semântico, classes CSS BEM (emergencia-form__field, emergencia-form__input--error) e data-attributes para o JS (data-emergencia-cep, data-emergencia-submit). Zero lógica PHP no template.

Tabela de campos meta do CPT `emergencia_fossa`

Meta key Tipo Descrição Exemplo
nome string Nome completo do solicitante “João da Silva”
telefone string Apenas dígitos (DDD + número) “11999998888”
cep_validado string 8 dígitos, validado via ViaCEP “01310100”
endereco_completo string Logradouro + nº + complemento + bairro + cidade/UF “Av. Paulista, 1000 - Bela Vista, São Paulo/SP”
tipo_emergencia string Enum controlado “transbordamento”
prioridade int 1=baixa, 2=media, 3=alta, 4=critica (auto) 4
status_atendimento string pendente, a_caminho, em_atendimento, concluido, cancelado “a_caminho”
tecnico_atribuido int User ID do técnico (WP_User) 42
whatsapp_enviado_em datetime Timestamp do envio à equipe “2024-01-15 03:12:07”
lgpd_consent bool Checkbox marcado no submit true
lgpd_policy_version string Versão da política no momento “v2.1-2024”

Essa estrutura permite relatórios gerenciais (tempo médio de resposta por tipo, carga por técnico, reincidência por endereço) sem ETL complexo.

Conclusão prática

Um formulário de emergência para limpeza de fossa séptica bem implementado transforma o site em extensão da operação de campo: captura dados limpos, notifica a equipe certa em segundos, cumpre a lei e funciona quando o servidor está sob estresse. Comece pelo plugin enxuto, valide cada campo dos dois lados, use filas para integrações externas e meça tudo. O próximo passo é conectar este formulário a um painel de gestão de equipes de plantão para fechar o ciclo do atendimento. Para operação real na capital, conte com limpeza de fossa séptica na cidade de São Paulo como referência de integração campo-tecnologia. Seu código deve ser tão confiável quanto o caminhão que sai da garagem às 3h da manhã.

Checklist prático

0 de 9 concluídos

Perguntas frequentes

Como garantir que o formulário de emergência funcione 24 horas sem interrupção?

Hospede o site em servidor com SLA de 99,9% e utilize cache de borda (CDN) para manter o formulário acessível mesmo durante picos de tráfego. Implemente monitoramento de uptime com alertas via SMS/email para a equipe técnica.

Qual a melhor forma de validar o CEP e endereço no formulário de fossa séptica?

Integre a API dos Correios (ViaCEP) para preenchimento automático de logradouro, bairro e cidade ao digitar o CEP. Adicione validação client-side com JavaScript e server-side no PHP para evitar dados inconsistentes.

Como integrar o formulário ao WhatsApp Business para atendimento imediato?

Use a WhatsApp Business API oficial com webhook para receber mensagens. Configure template de mensagem pré-aprovado com variáveis dinâmicas (nome, endereço, tipo de emergência) para envio automático ao submeter o formulário.

É necessário LGPD para formulários de emergência de saneamento?

Sim. Todo formulário que coleta dados pessoais (nome, telefone, endereço) deve ter consentimento explícito, política de privacidade acessível e opção de exclusão de dados. Armazene logs de consentimento com timestamp e versão da política.

Como otimizar o Core Web Vitals em formulários de emergência pesados?

Carregue scripts de validação e mapas sob demanda (lazy-load) após interação do usuário. Use `fetchpriority="high"` no botão de envio e minimize CSS/JS bloqueante. Prefira validação nativa HTML5 antes de bibliotecas externas.

Qual a arquitetura recomendada para plugin de formulário de emergência?

Separe em camadas: endpoints REST API para submissão, sanitização via `sanitize_*` functions, nonces para CSRF, e handlers assíncronos (Action Scheduler) para envio de notificações sem travar a resposta ao usuário.