Como integrar validação de CPF em lojas Shopify com Liquid e JavaScript

Aprenda a integrar validação de CPF em lojas Shopify usando Liquid, JavaScript e a API do CPFHub.io para reduzir fraudes no checkout.

Redação CPFHub.io
Redação CPFHub.io
··11 min de leitura
Como integrar validação de CPF em lojas Shopify com Liquid e JavaScript

Para integrar validação de CPF em lojas Shopify, adicione um campo com name="attributes[cpf]" no template Liquid do carrinho, aplique máscara e validação algorítmica em JavaScript e chame a API do CPFHub.io por meio de um proxy serverless que mantém a chave de API fora do frontend. No Shopify Plus, a Checkout Extensibility API permite adicionar o campo diretamente na etapa de checkout.

Introdução

O Shopify é uma das plataformas de e-commerce mais utilizadas no Brasil, permitindo que empreendedores criem lojas virtuais profissionais sem conhecimento técnico avançado. No mercado brasileiro, a coleta e validação do CPF no checkout é essencial -- tanto para emissão de nota fiscal quanto para prevenção de fraudes. Porém, o Shopify não oferece validação nativa de CPF. A solução é combinar customizações em Liquid (a linguagem de templates do Shopify) com JavaScript e uma API externa.


Desafios da validação de CPF no Shopify

O Shopify foi desenvolvido originalmente para o mercado internacional, onde o CPF não existe. Isso traz alguns desafios para lojas brasileiras.

Limitações do Shopify para o mercado brasileiro

  • Sem campo nativo de CPF -- O checkout padrão não possui campo específico para CPF.

  • Checkout limitado -- No Shopify Standard, a personalização do checkout é restrita. No Shopify Plus, há mais flexibilidade.

  • Sem validação backend -- O Shopify não oferece lógica de negócio customizada no servidor para validar campos personalizados.

  • Scripts limitados -- O Shopify limita a execução de JavaScript customizado por razões de segurança.

Soluções disponíveis

  • Additional note attributes -- Campos adicionais no checkout usando note attributes.

  • Shopify Plus Checkout Extensions -- Para lojistas no plano Plus, extensões customizadas do checkout.

  • Apps de terceiros -- Apps da Shopify App Store que adicionam campo de CPF.

  • Customização do tema -- Adicionar campo de CPF em páginas do carrinho ou formulários pré-checkout.


Abordagem 1: campo de CPF no carrinho (Liquid + JavaScript)

Para lojas no Shopify Standard (não Plus), a abordagem mais comum é adicionar o campo de CPF na página do carrinho, antes do checkout.

Adicionando o campo de CPF no tema (Liquid)

Edite o arquivo do tema responsável pela página do carrinho. Normalmente é templates/cart.liquid ou sections/cart-template.liquid.

Adicione o seguinte bloco dentro do formulário do carrinho:

<div class="cpf-validation-wrapper" style="margin: 20px 0;">
    <label for="cart-cpf" style="display: block; margin-bottom: 6px; font-weight: bold;">
    CPF (obrigatório)
    </label>
    <div style="display: flex; gap: 8px; align-items: center;">
    <input
    type="text"
    id="cart-cpf"
    name="attributes[cpf]"
    placeholder="000.000.000-00"
    inputmode="numeric"
    maxlength="14"
    required
    style="padding: 10px; border: 1px solid #ccc; border-radius: 4px; flex: 1; font-size: 16px;"
    value="{{ cart.attributes.cpf }}"
    />
    <button
    type="button"
    id="btn-validar-cpf"
    style="padding: 10px 16px; background: #2563eb; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px;"
    >
    Validar
    </button>
    </div>
    <div id="cpf-feedback" style="margin-top: 6px; font-size: 14px; min-height: 20px;"></div>
</div>

O atributo name="attributes[cpf]" garante que o CPF seja armazenado como cart attribute e acompanhe o pedido.


JavaScript de validação

Adicione o seguinte JavaScript no tema. No Shopify, você pode colocar em assets/cpf-validation.js e incluí-lo no layout, ou adicionar diretamente no tema.

Código JavaScript completo

(function() {
    'use strict';

    var cpfInput = document.getElementById('cart-cpf');
    var btnValidar = document.getElementById('btn-validar-cpf');
    var feedback = document.getElementById('cpf-feedback');
    var form = cpfInput ? cpfInput.closest('form') : null;
    var cpfValidado = false;

    if (!cpfInput || !btnValidar || !feedback) return;

    // Máscara de CPF
    cpfInput.addEventListener('input', function(e) {
    var valor = e.target.value.replace(/\D/g, '');
    if (valor.length > 11) valor = valor.substring(0, 11);

    if (valor.length > 9) {
    valor = valor.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4');
    } else if (valor.length > 6) {
    valor = valor.replace(/(\d{3})(\d{3})(\d{1,3})/, '$1.$2.$3');
    } else if (valor.length > 3) {
    valor = valor.replace(/(\d{3})(\d{1,3})/, '$1.$2');
    }

    e.target.value = valor;
    cpfValidado = false;
    feedback.textContent = '';
    });

    // Validação de dígitos locais
    function validarDigitosCPF(cpf) {
    if (cpf.length !== 11) return false;
    if (/^(\d)\1{10}$/.test(cpf)) return false;

    var soma = 0;
    for (var i = 0; i < 9; i++) {
    soma += parseInt(cpf[i]) * (10 - i);
    }
    var resto = (soma * 10) % 11;
    if (resto === 10) resto = 0;
    if (resto !== parseInt(cpf[9])) return false;

    soma = 0;
    for (var i = 0; i < 10; i++) {
    soma += parseInt(cpf[i]) * (11 - i);
    }
    resto = (soma * 10) % 11;
    if (resto === 10) resto = 0;
    return resto === parseInt(cpf[10]);
    }

    // Validar via API (através de proxy)
    async function validarCPFAPI(cpf) {
    try {
    var response = await fetch('https://seu-proxy.com/api/validar-cpf', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ cpf: cpf })
    });

    return await response.json();
    } catch (e) {
    return null;
    }
    }

    // Botão de validação
    btnValidar.addEventListener('click', async function() {
    var cpf = cpfInput.value.replace(/\D/g, '');

    if (cpf.length !== 11) {
    feedback.textContent = 'CPF deve ter 11 dígitos.';
    feedback.style.color = '#dc2626';
    return;
    }

    if (!validarDigitosCPF(cpf)) {
    feedback.textContent = 'CPF com dígitos verificadores inválidos.';
    feedback.style.color = '#dc2626';
    return;
    }

    feedback.textContent = 'Validando...';
    feedback.style.color = '#666';
    btnValidar.disabled = true;

    var resultado = await validarCPFAPI(cpf);

    if (resultado && resultado.success) {
    feedback.textContent = 'CPF válido - ' + resultado.data.name;
    feedback.style.color = '#16a34a';
    cpfValidado = true;
    } else if (resultado) {
    feedback.textContent = 'CPF não encontrado. Verifique o número.';
    feedback.style.color = '#dc2626';
    cpfValidado = false;
    } else {
    // Fallback: se a API não respondeu, aceitar validação local
    feedback.textContent = 'CPF com formato válido (verificação online indisponível).';
    feedback.style.color = '#d97706';
    cpfValidado = true;
    }

    btnValidar.disabled = false;
    });

    // Impedir checkout sem CPF validado
    if (form) {
    form.addEventListener('submit', function(e) {
    var cpf = cpfInput.value.replace(/\D/g, '');

    if (cpf.length !== 11) {
    e.preventDefault();
    feedback.textContent = 'Informe um CPF válido para continuar.';
    feedback.style.color = '#dc2626';
    cpfInput.focus();
    return;
    }

    if (!cpfValidado) {
    e.preventDefault();
    feedback.textContent = 'Valide o CPF antes de prosseguir.';
    feedback.style.color = '#dc2626';
    cpfInput.focus();
    }
    });
    }
})();

Proxy para proteger a chave de API

A chave de API nunca deve ficar exposta no frontend do Shopify. Crie um proxy simples (serverless function ou servidor) que intermedie a comunicação.

Exemplo de proxy (Node.js)

// api/validar-cpf.js (Vercel, Netlify ou similar)

export default async function handler(req, res) {
    res.setHeader('Access-Control-Allow-Origin', 'https://sua-loja.myshopify.com');
    res.setHeader('Access-Control-Allow-Methods', 'POST');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

    if (req.method === 'OPTIONS') return res.status(200).end();
    if (req.method !== 'POST') return res.status(405).end();

    const { cpf } = req.body;
    const cpfLimpo = cpf.replace(/\D/g, '');

    if (cpfLimpo.length !== 11) {
    return res.status(400).json({ success: false, erro: 'CPF inválido' });
    }

    try {
    const response = await fetch(
    `https://api.cpfhub.io/cpf/${cpfLimpo}`,
    {
    headers: {
    'x-api-key': process.env.CPFHUB_API_KEY,
    'Accept': 'application/json'
    },
    signal: AbortSignal.timeout(10000)
    }
    );

    const dados = await response.json();
    return res.status(200).json(dados);
    } catch (erro) {
    return res.status(500).json({ success: false, erro: 'Falha na validação' });
    }
}

Para referência, a chamada direta à API via cURL:

curl -X GET https://api.cpfhub.io/cpf/12345678900 \
    -H "x-api-key: SUA_CHAVE_DE_API" \
    -H "Accept: application/json"

Abordagem 2: Shopify Plus com Checkout Extensions

Para lojistas no Shopify Plus, a Checkout Extensibility API permite adicionar campos customizados diretamente no checkout.

Shopify Checkout UI Extension

Crie uma extensão de checkout que adiciona o campo de CPF:

// extensions/cpf-validation/src/Checkout.jsx
import {
    reactExtension,
    TextField,
    Banner,
    useApplyAttributeChange,
} from '@shopify/ui-extensions-react/checkout';
import { useState } from 'react';

export default reactExtension(
    'purchase.checkout.contact.render-after',
    () => <CPFField />
);

function CPFField() {
    const [cpf, setCPF] = useState('');
    const [mensagem, setMensagem] = useState('');
    const [erro, setErro] = useState(false);
    const applyAttributeChange = useApplyAttributeChange();

    const handleChange = (value) => {
    let limpo = value.replace(/\D/g, '').substring(0, 11);

    if (limpo.length > 9) {
    limpo = limpo.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4');
    } else if (limpo.length > 6) {
    limpo = limpo.replace(/(\d{3})(\d{3})(\d{1,3})/, '$1.$2.$3');
    } else if (limpo.length > 3) {
    limpo = limpo.replace(/(\d{3})(\d{1,3})/, '$1.$2');
    }

    setCPF(limpo);
    setMensagem('');
    setErro(false);
    };

    const handleBlur = async () => {
    const cpfLimpo = cpf.replace(/\D/g, '');
    if (cpfLimpo.length !== 11) {
    setErro(true);
    setMensagem('CPF deve ter 11 dígitos');
    return;
    }

    try {
    const response = await fetch(
    `https://seu-proxy.com/api/validar-cpf`,
    {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ cpf: cpfLimpo })
    }
    );

    const dados = await response.json();

    if (dados.success) {
    setErro(false);
    setMensagem('CPF válido - ' + dados.data.name);
    await applyAttributeChange({
    type: 'updateAttribute',
    key: 'cpf',
    value: cpfLimpo
    });
    } else {
    setErro(true);
    setMensagem('CPF não encontrado');
    }
    } catch (e) {
    setErro(true);
    setMensagem('Erro na validação');
    }
    };

    return (
    <>
    <TextField
    label="CPF"
    value={cpf}
    onChange={handleChange}
    onBlur={handleBlur}
    required
    />
    {mensagem && (
    <Banner status={erro ? 'critical' : 'success'}>
    {mensagem}
    </Banner>
    )}
    </>
    );
}

Acessando o CPF no pedido

Depois que o CPF é salvo como cart attribute, ele aparece nos detalhes do pedido no admin do Shopify. Também pode ser acessado via API do Shopify para integração com sistemas de emissão de nota fiscal.

Via Shopify Admin API

// Consultando o pedido e obtendo o CPF
const response = await fetch(
    'https://sua-loja.myshopify.com/admin/api/2024-04/orders/{order_id}.json',
    {
    headers: {
    'X-Shopify-Access-Token': 'SEU_TOKEN_SHOPIFY'
    }
    }
);

const pedido = await response.json();
const cpf = pedido.order.note_attributes.find(
    attr => attr.name === 'cpf'
)?.value;

Benefícios da validação de CPF no Shopify

BenefícioImpacto
Redução de chargebacksAté 90% menos contestações
Notas fiscais corretasEliminação de rejeições pela SEFAZ
Prevenção de fraudesBarreira contra compras com dados falsos
Base de clientes limpaDados verificados desde o primeiro pedido
Conformidade fiscalCPF correto em todos os documentos

O plano gratuito do CPFHub.io oferece 50 consultas mensais sem cartão de crédito — suficiente para testar a integração em ambiente de desenvolvimento e nos primeiros pedidos da loja. Para operações de maior volume, o plano Pro cobre 1.000 consultas por mês por R$149, e consultas adicionais são cobradas a R$0,15 cada, sem bloqueio da API.


Planos recomendados para Shopify

Porte da lojaPlano CPFHub.ioPreço
Loja em testeGrátis (R$ 0)50 consultas/mês
Loja ativaPro (R$ 149/mês)1.000 consultas/mês
Alto volumeCorporativoSob consulta

Perguntas frequentes

Posso adicionar o campo de CPF diretamente no checkout do Shopify Standard?

No Shopify Standard, o checkout é fechado para customização direta. A abordagem recomendada é adicionar o campo na página do carrinho, antes de o cliente clicar em "Finalizar compra". O CPF fica salvo como cart attribute e acompanha o pedido automaticamente. Apenas o Shopify Plus permite modificar a página de checkout via Checkout Extensions.

O CPF salvo como cart attribute aparece no painel de pedidos do Shopify?

Sim. Cart attributes aparecem na seção "Notas e informações adicionais" nos detalhes de cada pedido no admin do Shopify. Também estão disponíveis via Shopify Admin API no campo note_attributes, o que facilita a integração com sistemas de emissão de nota fiscal e ERPs.

Como garantir conformidade com a LGPD ao coletar CPF no Shopify?

Informe ao cliente a finalidade da coleta (emissão de NF, antifraude) no próprio formulário ou na política de privacidade da loja. Não exporte ou compartilhe o CPF com apps de terceiros sem necessidade. A ANPD orienta que dados de identificação devem ser tratados com o princípio da necessidade e com base legal declarada.

Por que usar um proxy em vez de chamar a API diretamente no JavaScript da loja?

A chave de API do CPFHub.io nunca deve ficar exposta no código frontend — qualquer visitante pode inspecionar o JavaScript da página e roubar a chave. Um proxy serverless (Vercel, Netlify Functions, Cloudflare Workers) recebe o CPF do frontend, chama a API com a chave armazenada como variável de ambiente e devolve apenas o resultado necessário, mantendo a chave protegida.


Conclusão

Integrar validação de CPF em lojas Shopify é possível e recomendável para o mercado brasileiro, mesmo com as limitações da plataforma. A combinação de Liquid para o campo visual, JavaScript para a interação e um proxy com a API do CPFHub.io para a validação em tempo real cria uma solução completa que previne fraudes, garante notas fiscais corretas e melhora a qualidade da base de clientes. Para lojistas no Shopify Plus, as Checkout Extensions oferecem ainda mais controle sobre a experiência de checkout.

Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e adicione validação de CPF à sua loja Shopify para reduzir fraudes e garantir notas fiscais corretas desde o primeiro pedido.

CPFHub.io

Pronto para integrar a API?

50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.

Redação CPFHub.io

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.

WhatsAppFale conosco via WhatsApp