Para integrar validação de CPF em WordPress com Elementor e AJAX, crie um plugin que registra um handler no admin-ajax.php, faz a chamada server-side para https://api.cpfhub.io/cpf/{CPF} com o header x-api-key e retorna o resultado ao JavaScript do formulário. Essa arquitetura mantém a chave de API protegida no servidor e entrega feedback visual ao usuário sem recarregar a página. A latência média da API é de ~900ms, então um indicador de carregamento melhora a percepção de velocidade. A documentação do WordPress para requisições HTTP explica como usar wp_remote_get de forma correta e segura.
Arquitetura da solução
A integração segue o padrão WordPress para requisições AJAX:
- O usuário digita o CPF no campo do formulário Elementor.
- Um script JavaScript captura o evento e envia uma requisição AJAX para o
admin-ajax.php. - O PHP no servidor recebe a requisição, consulta a API da CPFHub e retorna o resultado.
- O JavaScript atualiza o formulário com os dados recebidos.
Essa abordagem mantém a chave de API protegida no servidor, seguindo as boas práticas de segurança do WordPress.
Criando o plugin de validação
Crie um plugin WordPress dedicado para manter o código organizado e facilitar atualizações:
<?php
/**
* Plugin Name: CPFHub Validator
* Description: Validação de CPF em tempo real com a API CPFHub.io
* Version: 1.0.0
* Author: Sua Empresa
*/
defined('ABSPATH') || exit;
class CPFHub_Validator {
private $api_key;
public function __construct() {
$this->api_key = get_option('cpfhub_api_key', '');
add_action('wp_enqueue_scripts', [$this, 'enqueue_scripts']);
add_action('wp_ajax_cpfhub_validate', [$this, 'ajax_validate']);
add_action('wp_ajax_nopriv_cpfhub_validate', [$this, 'ajax_validate']);
add_action('admin_menu', [$this, 'add_settings_page']);
add_action('admin_init', [$this, 'register_settings']);
}
public function enqueue_scripts() {
if ($this->should_load_scripts()) {
wp_enqueue_script(
'cpfhub-validator',
plugin_dir_url(__FILE__) . 'js/cpfhub-validator.js',
[],
'1.0.0',
true
);
wp_localize_script('cpfhub-validator', 'cpfhubConfig', [
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('cpfhub_validate'),
]);
wp_enqueue_style(
'cpfhub-validator',
plugin_dir_url(__FILE__) . 'css/cpfhub-validator.css',
[],
'1.0.0'
);
}
}
public function ajax_validate() {
check_ajax_referer('cpfhub_validate', 'nonce');
$cpf = preg_replace('/\D/', '', sanitize_text_field($_POST['cpf'] ?? ''));
if (strlen($cpf) !== 11) {
wp_send_json_error(['message' => 'CPF deve conter 11 dígitos.']);
}
$response = wp_remote_get(
"https://api.cpfhub.io/cpf/{$cpf}",
[
'headers' => [
'x-api-key' => $this->api_key,
'Accept' => 'application/json',
],
'timeout' => 10,
]
);
if (is_wp_error($response)) {
wp_send_json_error([
'message' => 'Erro na comunicação com a API. Tente novamente.'
]);
}
$body = json_decode(wp_remote_retrieve_body($response), true);
if (!empty($body['success']) && $body['success'] === true) {
wp_send_json_success($body['data']);
} else {
wp_send_json_error([
'message' => 'CPF não encontrado na base de dados.'
]);
}
}
private function should_load_scripts() {
return !empty($this->api_key);
}
public function add_settings_page() {
add_options_page(
'CPFHub Validator',
'CPFHub Validator',
'manage_options',
'cpfhub-validator',
[$this, 'render_settings_page']
);
}
public function register_settings() {
register_setting('cpfhub_settings', 'cpfhub_api_key');
}
public function render_settings_page() {
?>
<div class="wrap">
<h1>CPFHub Validator</h1>
<form method="post" action="options.php">
<?php settings_fields('cpfhub_settings'); ?>
<table class="form-table">
<tr>
<th>Chave de API</th>
<td>
<input type="text"
name="cpfhub_api_key"
value="<?php echo esc_attr(get_option('cpfhub_api_key')); ?>"
class="regular-text" />
<p class="description">
Obtenha sua chave em
<a href="https://www.cpfhub.io/" target="_blank">cpfhub.io</a>
</p>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php
}
}
new CPFHub_Validator();
Criando o JavaScript para AJAX
Crie o arquivo js/cpfhub-validator.js dentro do diretório do plugin:
// js/cpfhub-validator.js
(function () {
"use strict";
let debounceTimer = null;
function init() {
const cpfFields = document.querySelectorAll(
'input[name="form_fields[cpf]"], input[data-cpfhub="true"], .cpfhub-field input'
);
cpfFields.forEach(function (field) {
field.setAttribute("inputmode", "numeric");
field.setAttribute("maxlength", "14");
const feedbackEl = document.createElement("div");
feedbackEl.className = "cpfhub-feedback";
field.parentNode.appendChild(feedbackEl);
field.addEventListener("input", function () {
formatCpf(field);
debouncedValidate(field, feedbackEl);
});
});
}
function formatCpf(field) {
let value = field.value.replace(/\D/g, "");
if (value.length > 11) value = value.slice(0, 11);
if (value.length > 9) {
value = value.replace(/(\d{3})(\d{3})(\d{3})(\d{1,2})/, "$1.$2.$3-$4");
} else if (value.length > 6) {
value = value.replace(/(\d{3})(\d{3})(\d{1,3})/, "$1.$2.$3");
} else if (value.length > 3) {
value = value.replace(/(\d{3})(\d{1,3})/, "$1.$2");
}
field.value = value;
}
function debouncedValidate(field, feedbackEl) {
if (debounceTimer) clearTimeout(debounceTimer);
debounceTimer = setTimeout(function () {
const cpf = field.value.replace(/\D/g, "");
if (cpf.length !== 11) {
feedbackEl.textContent = "";
feedbackEl.className = "cpfhub-feedback";
return;
}
validateCpf(cpf, field, feedbackEl);
}, 600);
}
function validateCpf(cpf, field, feedbackEl) {
feedbackEl.textContent = "Validando CPF...";
feedbackEl.className = "cpfhub-feedback cpfhub-loading";
const formData = new FormData();
formData.append("action", "cpfhub_validate");
formData.append("nonce", cpfhubConfig.nonce);
formData.append("cpf", cpf);
const controller = new AbortController();
const timeoutId = setTimeout(function () {
controller.abort();
}, 15000);
fetch(cpfhubConfig.ajaxUrl, {
method: "POST",
body: formData,
signal: controller.signal,
})
.then(function (response) {
clearTimeout(timeoutId);
return response.json();
})
.then(function (result) {
if (result.success) {
feedbackEl.textContent = "CPF válido - " + result.data.name;
feedbackEl.className = "cpfhub-feedback cpfhub-success";
fillFormFields(result.data);
} else {
feedbackEl.textContent =
result.data?.message || "CPF não encontrado.";
feedbackEl.className = "cpfhub-feedback cpfhub-error";
}
})
.catch(function (error) {
clearTimeout(timeoutId);
if (error.name === "AbortError") {
feedbackEl.textContent = "Tempo excedido. Tente novamente.";
} else {
feedbackEl.textContent = "Erro na validação. Tente novamente.";
}
feedbackEl.className = "cpfhub-feedback cpfhub-error";
});
}
function fillFormFields(data) {
const nameFields = document.querySelectorAll(
'input[name="form_fields[name]"], input[data-cpfhub-fill="name"]'
);
nameFields.forEach(function (f) {
f.value = data.name || "";
});
const birthFields = document.querySelectorAll(
'input[name="form_fields[birth_date]"], input[data-cpfhub-fill="birthDate"]'
);
birthFields.forEach(function (f) {
f.value = data.birthDate || "";
});
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
})();
Configurando o formulário no Elementor
Com Elementor Pro (Form Widget)
- Adicione um widget Form na página.
- Adicione um campo de texto com ID
cpf. - Adicione campos para
nameebirth_dateque serão preenchidos automaticamente. - No campo de CPF, adicione a classe CSS
cpfhub-fieldem Advanced > CSS Classes.
Com Elementor Free (HTML Widget)
Se você usa a versão gratuita, insira o formulário via widget HTML:
<form id="cpfhub-registration" class="cpfhub-form">
<div class="cpfhub-form-group">
<label for="cpf-field">CPF</label>
<input
type="text"
id="cpf-field"
data-cpfhub="true"
placeholder="000.000.000-00"
inputmode="numeric"
required
/>
</div>
<div class="cpfhub-form-group">
<label for="name-field">Nome Completo</label>
<input
type="text"
id="name-field"
data-cpfhub-fill="name"
readonly
/>
</div>
<div class="cpfhub-form-group">
<label for="birth-field">Data de Nascimento</label>
<input
type="text"
id="birth-field"
data-cpfhub-fill="birthDate"
readonly
/>
</div>
<button type="submit" class="cpfhub-submit">Cadastrar</button>
</form>
Estilos CSS para feedback visual
Crie o arquivo css/cpfhub-validator.css:
/* css/cpfhub-validator.css */
.cpfhub-feedback {
margin-top: 4px;
font-size: 13px;
min-height: 20px;
transition: all 0.3s ease;
}
.cpfhub-loading {
color: #6b7280;
}
.cpfhub-loading::before {
content: "";
display: inline-block;
width: 12px;
height: 12px;
border: 2px solid #6b7280;
border-top-color: transparent;
border-radius: 50%;
animation: cpfhub-spin 0.6s linear infinite;
margin-right: 6px;
vertical-align: middle;
}
.cpfhub-success {
color: #059669;
font-weight: 500;
}
.cpfhub-error {
color: #dc2626;
}
@keyframes cpfhub-spin {
to {
transform: rotate(360deg);
}
}
.cpfhub-form-group {
margin-bottom: 16px;
}
.cpfhub-form-group label {
display: block;
margin-bottom: 4px;
font-weight: 600;
}
.cpfhub-form-group input {
width: 100%;
padding: 10px 12px;
border: 1px solid #d1d5db;
border-radius: 6px;
font-size: 16px;
}
.cpfhub-form-group input:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.cpfhub-form-group input[readonly] {
background-color: #f9fafb;
cursor: not-allowed;
}
Segurança e boas práticas
Proteção com nonce
O WordPress usa nonces para proteger requisições AJAX contra CSRF. Nosso plugin já implementa isso com wp_create_nonce e check_ajax_referer.
Rate limiting no servidor
Adicione proteção contra abusos:
public function ajax_validate() {
check_ajax_referer('cpfhub_validate', 'nonce');
$ip = $_SERVER['REMOTE_ADDR'];
$transient_key = 'cpfhub_rate_' . md5($ip);
$count = (int) get_transient($transient_key);
if ($count >= 10) {
wp_send_json_error([
'message' => 'Muitas tentativas. Aguarde um minuto.'
]);
}
set_transient($transient_key, $count + 1, 60);
// ... restante da validação
}
Perguntas frequentes
Como a chave de API da CPFHub.io é protegida nessa integração com WordPress?
A chave de API fica armazenada na tabela de opções do WordPress, acessada via get_option('cpfhub_api_key'), e nunca é exposta no frontend. Todo o tráfego com a API passa pelo admin-ajax.php no servidor, de modo que o JavaScript do navegador jamais vê a chave diretamente. Isso segue o padrão recomendado pela documentação de segurança do WordPress.
A API CPFHub.io bloqueia requisições quando o limite do plano é atingido?
Não. Quando o limite mensal de consultas é ultrapassado, a API continua respondendo normalmente e cobra R$0,15 por consulta adicional — sem retornar erro 429 nem interromper o serviço. O plano gratuito inclui 50 consultas por mês; o plano Pro oferece 1.000 consultas mensais por R$149, com o mesmo modelo de excedente.
O plugin funciona com o Elementor Free ou apenas com o Pro?
O plugin funciona com ambas as versões. Com o Elementor Pro, basta adicionar a classe cpfhub-field no campo de CPF do Form Widget. Com o Elementor Free, use o HTML Widget para inserir o formulário diretamente com os atributos data-cpfhub="true" nos campos adequados — o JavaScript do plugin detecta e inicializa automaticamente.
Qual o tempo de resposta esperado da API e como configurar o timeout corretamente?
A latência média da API CPFHub.io é de aproximadamente 900ms. Por isso, o plugin configura 'timeout' => 10 na chamada via wp_remote_get e 15 segundos de timeout no AbortController do JavaScript — margem suficiente para a grande maioria das conexões. O indicador de carregamento exibido durante a validação evita que o usuário submeta o formulário antes da resposta chegar.
Conclusão
Integrar validação de CPF em WordPress com Elementor e AJAX é uma solução prática e segura que beneficia sites de e-commerce, landing pages e portais de cadastro. O plugin que construímos mantém a chave de API protegida no servidor, usa nonces para segurança e oferece feedback visual instantâneo ao usuário.
A API do CPFHub.io
Cadastre-se em cpfhub.io
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



