O JSON (JavaScript Object Notation) é um formato de troca de dados simples entre sistemas, processo também conhecido como parsing. Através de uma configuração de troca de dados, é possível integrar sistemas web, sites ou formulários em geral ao PipeRun.
Por exemplo: você pode configurar o envio de dados coletados através de uma landing page diretamente para o CRM de vendas PipeRun e gerar uma nova oportunidade, de forma automática.
Atenção! Este artigo exige conhecimentos técnicos em programação, tendo em vista que será necessário configurar as regras de envio de dados da integração em um JSON e inserir um script na página da landing page.
Confira neste artigo como realizar a configuração da integração. Também disponibilizamos uma explicação em vídeo, logo abaixo.
TÓPICOS DO ARTIGO
Exemplo de código em funcionamento, em um formulário para testes
CONFIGURANDO UMA INTEGRAÇÃO JSON
Informações gerais para envio de dados:
Endpoint:
https://api.pipe.run/v1/integrations/json/ingest/{HASH_DA_ETAPA_DO_FUNIL}Tipo de requisição:
POSTTipo de conteúdo (Content-Type):
application/json
É necessário ter o ID do formulário a ser integrado e o código precisa ser adaptado à realidade da integração.
Para saber como localizar a hash da etapa do funil, acesse este artigo.
JSON DE REGRAS (ENVIO NÃO OBRIGATÓRIO)
Confira abaixo o código, juntamente com a descrição, contendo as regras do envio dos dados:
{
"rules": {
"filter_situation_update": "informe_aqui_o_valor",
//NOME: FILTER_SITUATION_UPDATE
DESCRICAO: SE JÁ HOUVER UMA OPORTUNIDADE COM A SITUAÇÃO INFORMADA(E COM O MESMO ID),
SERÁ ATUALIZADA ESSA
OPORTUNIDADE,
CASO CONTRARIO,
UMA NOVA SERÁ CRIADA..
VALORES: {
"unfreezed", // NORMAL ou descongelada
"freezed", // CONGELADA
"undeleted", // NORMAL ou fora da lixeira
"deleted" // NA LIXEIRA
}
PADRÃO: "NULL" // NULO ou oportunidade aberta normal.
/
"equal_pipeline": "informe_aqui_o_valor",
/
NOME: EQUAL_PIPELINE
DESCRICAO: DETERMINA O FUNIL PARA BUSCAR A OP POR SER ATUALIZADA
VALORES: {
true, // BUSCARÁ A OP NO MESMO FUNIL DA ETAPA RECEBIDA ATRAVÉS DA HASH
false // BUSCARÁ A OP INDEPENDENTE DO FUNIL
}
PADRÃO: false
OBS: DEPENDE DA REGRA 'UPDATE' & amp;gt;
'TRUE' /
"status": "informe_aqui_o_valor",
/
NOME: STATUS
DESCRICAO: DETERMINA O STATUS DA OPORTUNIDADE
VALORES: {
"open", // ABERTA
"closed", // GANHA
"lost" // PERDIDA
}
PADRÃO: "open"
OBS: AÇÕES AUTOMÁTICAS SERÃO EXECUTADAS,
DEPENDENDO DO GATILHO /
"situation": "informe_aqui_o_valor",
/
NOME: SITUATION
DESCRICAO: DETERMINA A SITUAÇÃO DA OPORTUNIDADE
VALORES: {
"freezed", // CONGELA A OP
"unfreezed", // DESCONGELA A OP
"delete", // ENVIA PARA LIXEIRA A OP
"undelete", // RETIRA DA LIXEIRA A OP
}
PADRÃO: "NULL" // NULO
OBS: PERMITE MAIS DE UM VALOR NESSA REGRA,
DEVENDO SER SEPARADO POR ","(VÍRGULA) /
"validate_cpf": "informe_aqui_o_valor",
/
NOME: VALIDATE_CPF
DESCRICAO: DETERMINA BUSCA DA PESSOA
VALORES: {
true, // BUSCA A PESSOA ATRAVÉS DO ATRIBUTO 'CPF'
false // BUSCA A PESSOA ATRAVÉS DO ATRIBUTO 'EMAIL'
}
PADRÃO: false /
"validate_cnpj": "informe_aqui_o_valor" /
NOME: VALIDATE_CNPJ
DESCRICAO: DETERMINA BUSCA DA EMPRESA
VALORES: {
true, // BUSCA A EMPRESA ATRAVÉS DO ATRIBUTO 'CNPJ'
false // BUSCA A EMPRESA ATRAVÉS DO ATRIBUTO 'COMPANY'
}
PADRÃO: false /
"validate_person_phone": "informe_aqui_o_valor" /
NOME: VALIDATE_PERSON_PHONE
DESCRICAO: DETERMINA BUSCA DA PESSOA PELO TELEFONE
VALORES: {
true, // BUSCA A PESSOA ATRAVÉS DOS ATRIBUTOS 'PERSON_PHONE_MAIN, PERSONAL_PHONE'
false // BUSCA A PESSOA ATRAVÉS DO ATRIBUTO 'EMAIL'
}
PADRÃO: false /
}
}Ao atualizar oportunidades com update: true, o comportamento da etapa pode ser controlado com update_stage_hash: omita o campo para usar a etapa da hash da URL (padrão), envie null para manter a etapa atual da oportunidade, ou informe a hash de uma etapa específica para mover a oportunidade para ela.
JSON DO LEAD (ENVIO OBRIGATÓRIO)
Confira abaixo o código, juntamente com a descrição, do envio dos dados do lead.
{
"leads": [{
"id": "informe_aqui_o_valor", // OPORTUNIDADE: IDENTIFICADOR (PARA NÃO DUPLICAR)
"user": "informe_aqui_o_valor", // OPORTUNIDADE: DONO (NÃO OBRIGATÓRIO)
"title": "informe_aqui_o_valor", // OPORTUNIDADE: TITULO
"value": "informe_aqui_o_valor", // OPORTUNIDADE: VALOR DA NEGOCIAÇÃO
"value_mrr": "informe_aqui_o_valor", // OPORTUNIDADE: VALOR RECORRENTE
"email": "informe_aqui_o_valor", // PESSOA: E-MAIL
"name": "informe_aqui_o_valor", // PESSOA: NOME
"cpf": "informe_aqui_o_valor", // PESSOA: CPF
"birth_day": "informe_aqui_o_valor", // PESSOA: DATA DE NASCIMENTO
"person_phone_main": "informe_aqui_o_valor", // PESSOA: TELEFONE PRINCIPAL
"personal_phone": "informe_aqui_o_valor", // PESSOA: TELEFONE (OUTROS)
"public_url": "informe_aqui_o_valor", // PESSOA: URL PÚBLICO
"job_title": "informe_aqui_o_valor", // PESSOA: CARGO
"cnpj": "informe_aqui_o_valor", // EMPRESA: CNPJ
"company_website": "informe_aqui_o_valor", // EMPRESA: WEBSITE
"company": "informe_aqui_o_valor", // EMPRESA: NOME
"company_phone_main": "informe_aqui_o_valor", // EMPRESA: TELEFONE PRINCIPAL
"city_name": "informe_aqui_o_valor", // CIDADE: NOME (UTILIZADO EM EMPRESA/PESSOA)
"city_state": "informe_aqui_o_valor", // CIDADE: UF (UTILIZADO EM EMPRESA/PESSOA)
"last_conversion": {
"source": "informe_aqui_o_valor" // OPORTUNIDADE: ORIGEM
},
"custom_fields": {
"Nome do campo 1": "informe_aqui_o_valor", // OPORTUNIDADE: CAMPO CUSTOMIZADO
"Nome do campo 2": "informe_aqui_o_valor" // OPORTUNIDADE: CAMPO CUSTOMIZADO
},
"tags": [
"nome_da_tag 1", // OPORTUNIDADE: TAG
"nome_da_tag 2" // OPORTUNIDADE: TAG
],
"notes": [
"texto da nota 1", // OPORTUNIDADE: NOTAS
"texto da nota 2" // OPORTUNIDADE: NOTAS
]
}]
}EXEMPLO DO JSON DE REGRAS E LEAD
{
"rules": {
"update": true,
"equal_pipeline": false,
"validate_cpf": true,
"validate_cnpj": true,
"validate_person_phone": true,
"situation": "freezed,undelete",
"status": "open",
"filter_status_update": "open",
"filter_situation_update": "freezed"
},
"leads": [{
"user": "[email protected]",
"id": "[email protected]",
"title": "Teste OP via Json",
"name": "Pessoa 123",
"email": "[email protected]",
"cpf": "0123456789",
"person_phone_main": "(51) 33333334",
"personal_phone": "(51) 999999999",
"company": "Empresa 456",
"cnpj": "9876543210",
"company_website: "'https://meusite.com.br'",
"company_phone_main": "(51) 33333334",
"city_name": "Porto Alegre",
"city_state": "RS",
"last_conversion": {
"source": "Formulário Site"
},
"custom_fields": {
"Campo customizado teste 1": "Sim",
"Campo customizado teste 2": "(51) 123456789"
},
"tags": [
"Tag teste 1",
"Tag teste 2"
],
"notes": [
"Lead obtido através da integração com o formulário XYZ do site ABC."
]
}]
}Pontos importantes:
Caso o título não seja definido, o padrão
H:i d/m Integração: Nameserá utilizado;Caso o dono não seja definido, a oportunidade ficará sem dono. É possível utilizar uma distribuição de leads na etapa que a oportunidade for criada ou atualizada, caso não queira deixar fixo o dono da oportunidade no integrador.
Caso as tags informadas não existam, elas serão criadas e vinculadas, automaticamente;
Caso os campos customizados não existam, eles serão criados e vinculados automaticamente (serão campos do tipo "texto" por padrão. Para outros tipos de campos, o campo deverá ser criado previamente);
Você poderá utilizar o atributo
idpara evitar a duplicidade de leads, utilizando o dado informado para ser único junto a oportunidade. Dessa forma, antes de salvar, o PipeRun irá verificar se esse dado já existe vinculado a alguma oportunidade aberta, e, existindo o dado, será apenas atualizada a oportunidade, caso contrário, uma nova oportunidade será criada;É possível ainda atualizar oportunidades com status diferente de aberta, como perdida, ou ganha utilizando o parâmetro
filter_status_updatenas rules;Também é possível atualizar oportunidades que estejam na situação de congelada ou na lixeira, utilizando o parâmetro
filter_situation_update;Ao atualizar oportunidades com
update: true, o comportamento da etapa pode ser controlado comupdate_stage_hash:omita o campo para usar a etapa da hash da URL (padrão), envie null para manter a etapa atual da oportunidade, ou informe a hash de uma etapa específica para mover a oportunidade para ela.
O PipeRun devolverá um JSON com status de sucesso, caso tudo tenha funcionado, após realizar o cadastro.
{
"success": true,
"message": "OK",
"data": {
"id": ["1234"],
"hash": ["qkh5ei2qjkvvh9302yhp44zmtlyzxkz"]
}
}Com mais de um registro:
{
"success": true,
"message": "OK",
"data": {
"ids": ["1234", "1235"],
"hashes": ["qkh5ei2qjkvvh9302yhp44zmtlyzxkz", "b2t7xf1qjkvvh9302yhp44zmabcd9kz"]
}
}OUTROS EXEMPLOS
1. Código para captura de lead via integrador JSON com coleta de campanha através das variáveis UTM e conversão no Analytics
// MÉTODO PARA COLETAR DADOS DO FORMULÁRIO E ENVIAR PARA O PIPERUN, COM DADOS DE UTM.
// Dependências: jQuery, jQuery Validate, Google Analytics (ga).
<p>/* =========================================================================</p>
<ul>
<li>sessionStart.min.js</li>
<li>========================================================================= */</li>
</ul>
<p>function setCookie(name, value, exdays = 1) {
const date = new Date();
date.setTime(date.getTime() + exdays * 24 * 60 * 60 * 1000);
const expires = date.toUTCString();
document.cookie = name + "=" + value + "; expires=" + expires + "; path=/";
}</p>
<p>function getCookie(name) {
const cookies = document.cookie;</p>
<pre><code>if (cookies !== undefined &amp;&amp; cookies.length &gt; 0) {
const posCookie = cookies.indexOf(name);
if (posCookie &gt;= 0) {
let hashOportunidade = '';
const value = "; " + document.cookie;
const parts = value.split("; " + name + "=");
if (parts.length === 2) {
hashOportunidade = parts.pop().split(";").shift();
}
return hashOportunidade;
}
return false;
}
</code></pre>
<p>}</p>
<p>function eraseCookie(name) {
setCookie(name, '', -1);
}</p>
<p>function getRequestURL(name) {
const match = new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)').exec(location.search);</p>
<pre><code>if (match) {
return decodeURIComponent(match[1]);
}
</code></pre>
<p>}</p>
<p>var sessionStartCookie = {};
var sessionStart = {};
var SESSION_START_NAME = 'piperun_session';</p>
<p>function setSessionStart(
sessionStartName,
arTerms = [
'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',
'utm_position', 'utm_device', 'utm_match', 'utm_creative', 'plano', 'tipo'
]
) {
arTerms.forEach(function (termo) {
const nameTermo = sessionStartName + '_' + termo;
let termValue = ' ';
let boSet = false;</p>
<pre><code> sessionStartCookie[termo] = '';
sessionStart[termo] = '';
if (getRequestURL(termo)) {
termValue = getRequestURL(termo);
boSet = true;
}
if (!getCookie(nameTermo)) {
boSet = true;
}
if (boSet) {
setCookie(nameTermo, termValue);
}
termValue = getCookie(nameTermo);
if (termValue === '') {
termValue = ' ';
}
sessionStartCookie[termo] = termValue;
sessionStart[termo] = termValue;
});
</code></pre>
<p>}</p>
<p>// Persiste as UTMs em cookie no carregamento da página, preservando a
// atribuição mesmo se o usuário navegar antes de converter.
setSessionStart(SESSION_START_NAME);</p>
<p>/* =========================================================================</p>
<ul>
<li>Helpers</li>
<li>========================================================================= */</li>
</ul>
<p>// URL de referência:
// <a href="https://crmpiperun.com/?utm_source=google&utm_medium=cpc&utm_campaign=institucional">https://crmpiperun.com/?utm_source=google&utm_medium=cpc&utm_campaign=institucional</a>
function getParameterByName(name) {
name = name.replace(/[[]/, "\[").replace(/[]]/, "\]");
const regex = new RegExp("[?&]" + name + "=([^&#]*)");
const results = regex.exec(location.search);</p>
<pre><code>if (sessionStart &amp;&amp; sessionStart[name]) {
const value = sessionStart[name];
return (value === null || value === "" || value === " " || value === undefined) ? "" : value;
}
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
</code></pre>
<p>}</p>
<p>// Formatação de data: DD/M/YYYY H:M
function formatDate(date) {
return (date.getDate() < 10 ? '0' : '') + date.getDate() +
'/' + (date.getMonth() + 1) +
'/' + date.getFullYear() +
' ' + date.getHours() + ':' + date.getMinutes();
}</p>
<p>// Dispara evento de conversão: GA4 (gtag) com fallback para Universal Analytics (ga).
function trackConversion() {
if (typeof gtag === 'function') {
gtag('event', 'fale_consultor', {
event_category: 'form',
event_label: 'contato'
});
} else if (typeof ga === 'function') {
ga('send', 'event', 'form', 'contato', 'fale-consultor');
}
}</p>
<p>/* =========================================================================</p>
<ul>
<li>Envio do formulário</li>
<li>========================================================================= */</li>
</ul>
<p>const form = document.getElementById('conversion-form');
form.addEventListener('submit', enviarDados);</p>
<p>function enviarDados(event) {
// Impede o submit nativo; o envio é feito exclusivamente via AJAX.
event.preventDefault();</p>
<pre><code>if ($("#conversion-form").validate().errorList.length) {
return;
}
const submitButton = form.querySelector('[type="submit"]');
if (submitButton) {
submitButton.disabled = true; // evita envio duplicado
}
// ENDPOINT
const endpoint = "https://api.pipe.run/v1/integrations/json/ingest/aaaa0000-0a00-0a0a-0000-0aa000a00aa0";
const dataHora = formatDate(new Date());
const name = jQuery('#text_field-conversion-form').val();
const email = jQuery('#email_field-conversion-form').val();
const company = jQuery('#company_field-conversion-form').val();
const phone = jQuery('#phone_field-conversion-form').val();
const utm_source = getParameterByName('utm_source');
const utm_medium = getParameterByName('utm_medium');
const utm_campaign = getParameterByName('utm_campaign');
const utm_term = getParameterByName('utm_term');
const utm_content = getParameterByName('utm_content');
const utm_position = getParameterByName('utm_position');
const utm_device = getParameterByName('utm_device');
const utm_match = getParameterByName('utm_match');
const utm_creative = getParameterByName('utm_creative');
// RULES
const rules = {
"update": true,
"status": "open",
"equal_pipeline": true,
"filter_status_update": "open"
};
// LEAD
const lead = [{
"id": email,
"title": dataHora + " " + company,
"name": name,
"email": email,
"company": company,
"personal_phone": phone,
"last_conversion": {
"source": "Site_PipeRun"
},
"custom_fields": {
"url_conversao": location.href,
"utm_source": utm_source,
"utm_medium": utm_medium,
"utm_campaign": utm_campaign,
"utm_term": utm_term,
"utm_content": utm_content,
"utm_position": utm_position,
"utm_device": utm_device,
"utm_match": utm_match,
"utm_creative": utm_creative
},
"notes": [
"Título: " + dataHora + " Fale Consultor CRM&lt;br/&gt;" +
"E-mail: " + email + "&lt;br/&gt;" +
"Nome: " + name + "&lt;br/&gt;" +
"WhatsApp: " + phone + "&lt;br/&gt;" +
"Empresa: " + company + "&lt;br/&gt;" +
"utm_source: " + utm_source + "&lt;br/&gt;" +
"utm_medium: " + utm_medium + "&lt;br/&gt;" +
"utm_campaign: " + utm_campaign + "&lt;br/&gt;" +
"utm_term: " + utm_term + "&lt;br/&gt;" +
"utm_content: " + utm_content + "&lt;br/&gt;" +
"utm_position: " + utm_position + "&lt;br/&gt;" +
"utm_device: " + utm_device + "&lt;br/&gt;" +
"utm_match: " + utm_match + "&lt;br/&gt;" +
"utm_creative: " + utm_creative
]
}];
// Remove campos string vazios do lead
jQuery.each(lead[0], function (index, value) {
if (typeof value === 'string' &amp;&amp; value === '') {
delete lead[0][index];
}
});
// DATA
const dataToSend = {
"rules": rules,
"leads": lead
};
jQuery.ajax({
type: "post",
data: JSON.stringify(dataToSend),
dataType: "json",
url: endpoint,
success: function (data) {
trackConversion();
form.reset();
// TODO: exibir mensagem de sucesso ou redirecionar para página de obrigado.
},
error: function (xhr, status, error) {
console.error('[PipeRun] Falha ao enviar lead:', status, error, xhr.responseText);
alert('Não foi possível enviar seus dados. Tente novamente em instantes.');
},
complete: function () {
if (submitButton) {
submitButton.disabled = false;
}
}
});
</code></pre>
}
2. Código para controlar o comportamento da etapa ao atualizar uma oportunidade existente
Ao utilizar rules.update: true, é possível definir como a etapa da oportunidade deve se comportar durante a atualização através do parâmetro update_stage_hash.
Confira os três cenários possíveis:
Cenário 1: Mover para a etapa da hash da URL (comportamento padrão)
Não envie o campo update_stage_hash. A oportunidade será movida para a etapa definida pela hash informada no endpoint.
{
"rules": {
"update": true,
"equal_pipeline": true,
"filter_status_update": "open"
},
"leads": [{
"id": "<a href="mailto:<a href="mailto:<a href="mailto:[email protected]">[email protected]</a>"><a href="mailto:[email protected]">[email protected]</a></a>"><a href="mailto:<a href="mailto:[email protected]">[email protected]</a>"><a href="mailto:[email protected]">[email protected]</a></a></a>",
"name": "Nome do Contato",
"email": "<a href="mailto:<a href="mailto:<a href="mailto:[email protected]">[email protected]</a>"><a href="mailto:[email protected]">[email protected]</a></a>"><a href="mailto:<a href="mailto:[email protected]">[email protected]</a>"><a href="mailto:[email protected]">[email protected]</a></a></a>"
}]
}Cenário 2 : Manter a oportunidade na etapa atual
Envie rules.update_stage_hash: null. A oportunidade será atualizada sem ser movida de etapa.
{
"rules": {
"update": true,
"update_stage_hash": null,
"equal_pipeline": true,
"filter_status_update": "open"
},
"leads": [{
"id": "<a href="mailto:<a href="mailto:<a href="mailto:[email protected]">[email protected]</a>"><a href="mailto:[email protected]">[email protected]</a></a>"><a href="mailto:<a href="mailto:[email protected]">[email protected]</a>"><a href="mailto:[email protected]">[email protected]</a></a></a>",
"name": "Nome do Contato",
"email": "<a href="mailto:<a href="mailto:<a href="mailto:[email protected]">[email protected]</a>"><a href="mailto:[email protected]">[email protected]</a></a>"><a href="mailto:<a href="mailto:[email protected]">[email protected]</a>"><a href="mailto:[email protected]">[email protected]</a></a></a>"
}]
}Cenário 3: Mover para uma etapa específica
Envie em rules.update_stage_hash a hash da etapa desejada. A oportunidade será movida para essa etapa, independentemente da hash informada no endpoint.
{
"rules": {
"update": true,
"update_stage_hash": "hash_da_etapa_desejada",
"equal_pipeline": true,
"filter_status_update": "open"
},
"leads": [{
"id": "<a href="mailto:<a href="mailto:<a href="mailto:[email protected]">[email protected]</a>"><a href="mailto:[email protected]">[email protected]</a></a>"><a href="mailto:<a href="mailto:[email protected]">[email protected]</a>"><a href="mailto:[email protected]">[email protected]</a></a></a>",
"name": "Nome do Contato",
"email": "<a href="mailto:<a href="mailto:<a href="mailto:[email protected]">[email protected]</a>"><a href="mailto:[email protected]">[email protected]</a></a>"><a href="mailto:<a href="mailto:[email protected]">[email protected]</a>"><a href="mailto:[email protected]">[email protected]</a></a></a>"
}]
}Atenção! O parâmetro
update_stage_hashsó tem efeito quandorules.update: true.Integrações existentes que não enviarem esse campo continuam funcionando normalmente, sem nenhuma alteração de comportamento.
3. Código para captura de lead via integrador JSON com javascript puro, sem a necessidade de uso do jQuery
// Integrador JSON PipeRun — Landing Page CRM PipeRun
// Dependências: nenhuma (fetch nativo). GA4 (gtag) ou Universal Analytics (ga) opcionais.<p></p>
<p>const ENDPOINT = "<a href="https://api.pipe.run/v1/integrations/json/ingest/aaaa0000-0a00-0a0a-0000-0aa000a00aa0">https://api.pipe.run/v1/integrations/json/ingest/aaaa0000-0a00-0a0a-0000-0aa000a00aa0</a>";</p>
<p>// Retorna o valor do primeiro campo com o name informado, ou '' se não existir.
function getFieldValue(name) {
const field = document.getElementsByName(name)[0];</p>
<pre><code>return field ? field.value.trim() : '';
</code></pre>
<p>}</p>
<p>// Dispara evento de conversão: GA4 (gtag) com fallback para Universal Analytics (ga).
function trackConversion() {
if (typeof gtag === 'function') {
gtag('event', 'fale_consultor', {
event_category: 'form',
event_label: 'contato'
});
} else if (typeof ga === 'function') {
ga('send', 'event', 'form', 'contato', 'fale-consultor');
}
}</p>
<p>document.getElementById('button').addEventListener('click', function (event) {
// Se o botão estiver dentro de um <form>, impede o submit nativo.
event.preventDefault();</p>
<pre><code>const button = event.currentTarget;
const name = getFieldValue('name');
const email = getFieldValue('email');
const phone = getFieldValue('phone');
const segmento = getFieldValue('segmento');
// Validação mínima: o e-mail é o "id" do lead no integrador.
if (!email) {
alert('Informe um e-mail válido.');
return;
}
// RULES
const rules = {
"update": true,
"equal_pipeline": true,
"filter_status_update": "open"
};
// LEAD
const lead = [{
"id": email,
"title": "CRM PipeRun Landing Page",
"user": "[email protected]",
"name": name,
"email": email,
"personal_phone": phone,
"last_conversion": {
"source": "Site_CRMPipeRun"
},
"custom_fields": {
"segmento": segmento || "Não Informado"
},
"tags": [
"Contato"
],
"notes": [
"Contato enviado através do formulário de consultoria técnica do CRM PipeRun."
]
}];
// DATA
const dataToSend = {
"rules": rules,
"leads": lead
};
button.disabled = true; // evita envio duplicado
// Requisição POST
// Content-Type text/plain é intencional: evita preflight CORS (OPTIONS).
fetch(ENDPOINT, {
method: "POST",
headers: {
'Content-Type': 'text/plain'
},
body: JSON.stringify(dataToSend)
})
.then((response) =&gt; {
// fetch só rejeita em falha de rede; erros HTTP (4xx/5xx) chegam aqui.
if (!response.ok) {
return response.text().then((body) =&gt; {
throw new Error('HTTP ' + response.status + ': ' + body);
});
}
trackConversion();
// TODO: exibir mensagem de sucesso ou redirecionar para página de obrigado.
})
.catch((error) =&gt; {
console.error('[PipeRun] Falha ao enviar lead:', error);
alert('Não foi possível enviar seus dados. Tente novamente em instantes.');
})
.finally(() =&gt; {
button.disabled = false;
});
</code></pre>
});
4. Código para captura de lead via integrador JSON implementado no Wordpress com Elementor
// INTEGRAÇÃO ELEMENTOR FORM → PIPERUN, COM DADOS DE UTM.
// Dependências: jQuery (já carregado pelo WordPress/Elementor). GA4 (gtag) ou Universal Analytics (ga) opcionais.
// URL de referência:
// <a href="https://crmpiperun.com/?utm_source=google&utm_medium=cpc&utm_campaign=institucional">https://crmpiperun.com/?utm_source=google&utm_medium=cpc&utm_campaign=institucional</a><p></p>
<p>jQuery(function ($) {
const ENDPOINT = "<a href="https://api.pipe.run/v1/integrations/json/ingest/aaaa0000-0a00-0a0a-0000-0aa000a00aa0">https://api.pipe.run/v1/integrations/json/ingest/aaaa0000-0a00-0a0a-0000-0aa000a00aa0</a>";</p>
<pre><code>// Seletor do formulário alvo. Se houver mais de um form Elementor na página,
// restrinja pelo nome do form, ex.: '.elementor-form[name="Fale com Consultor"]'
const FORM_SELECTOR = '.elementor-form';
const UTM_TERMS = [
'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',
'utm_position', 'utm_device', 'utm_match', 'utm_creative'
];
const UTM_STORAGE_KEY = 'piperun_utms';
/* ---------------------------------------------------------------------
* UTMs: lê da URL e persiste na sessão, para não perder a atribuição
* quando o usuário navega entre páginas antes de converter.
* ------------------------------------------------------------------- */
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
const regex = new RegExp("[?&amp;]" + name + "=([^&amp;#]*)");
const results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
function loadStoredUtms() {
try {
return JSON.parse(sessionStorage.getItem(UTM_STORAGE_KEY)) || {};
} catch (e) {
return {};
}
}
function persistUtms() {
const fromUrl = {};
UTM_TERMS.forEach(function (term) {
const value = getParameterByName(term);
if (value) {
fromUrl[term] = value;
}
});
// Só sobrescreve se a URL atual trouxer UTMs (nova campanha).
if (Object.keys(fromUrl).length) {
try {
sessionStorage.setItem(UTM_STORAGE_KEY, JSON.stringify(fromUrl));
} catch (e) {
// sessionStorage indisponível (modo privado/bloqueado): segue sem persistir.
}
}
}
function getUtms() {
const stored = loadStoredUtms();
const utms = {};
UTM_TERMS.forEach(function (term) {
utms[term] = getParameterByName(term) || stored[term] || '';
});
return utms;
}
persistUtms();
/* ---------------------------------------------------------------------
* Helpers
* ------------------------------------------------------------------- */
// Formatação de data: DD/M/YYYY H:M
function formatDate(date) {
return (date.getDate() &lt; 10 ? '0' : '') + date.getDate() +
'/' + (date.getMonth() + 1) +
'/' + date.getFullYear() +
' ' + date.getHours() + ':' + date.getMinutes();
}
// Lê um campo do Elementor pelo ID configurado no editor (name="form_fields[&lt;id&gt;]"),
// escopado ao form, para não colidir com outros forms na página.
function getField($form, fieldId) {
const value = $form.find('[name="form_fields[' + fieldId + ']"]').val();
return value ? String(value).trim() : '';
}
// Dispara evento de conversão: GA4 (gtag) com fallback para Universal Analytics (ga).
function trackConversion() {
if (typeof gtag === 'function') {
gtag('event', 'captura_lead_corporativo', {
event_category: 'form',
event_label: 'contato'
});
} else if (typeof ga === 'function') {
ga('send', 'event', 'form', 'contato', 'captura_lead_corporativo');
}
}
/* ---------------------------------------------------------------------
* Montagem do payload
* ------------------------------------------------------------------- */
function buildPayload($form) {
const dataHora = formatDate(new Date());
const name = getField($form, 'nome');
const email = getField($form, 'email');
const company = getField($form, 'empresa');
const phone = getField($form, 'phone');
const job_title = getField($form, 'cargo');
const message = getField($form, 'message');
const utms = getUtms();
// RULES
const rules = {
"update": true,
"status": "open",
"equal_pipeline": true,
"filter_status_update": "open"
};
const notes =
"Título: " + dataHora + " Fale com Consultor CRM&lt;br/&gt;" +
"E-mail: " + email + "&lt;br/&gt;" +
"Nome: " + name + "&lt;br/&gt;" +
"WhatsApp: " + phone + "&lt;br/&gt;" +
"Empresa: " + company + "&lt;br/&gt;" +
"Cargo: " + job_title + "&lt;br/&gt;" +
"Mensagem: " + message + "&lt;br/&gt;" +
UTM_TERMS.map(function (term) {
return term + ": " + utms[term];
}).join("&lt;br/&gt;");
// LEAD
const lead = {
"id": email,
"title": dataHora + " " + company,
"name": name,
"email": email,
"company": company,
"personal_phone": phone,
"job_title": job_title,
"last_conversion": {
"source": utms.utm_source || "Site CRM PipeRun"
},
"custom_fields": Object.assign({ "url_conversao": location.href }, utms),
"notes": [notes]
};
// Remove campos string vazios do lead
Object.keys(lead).forEach(function (key) {
if (typeof lead[key] === 'string' &amp;&amp; lead[key] === '') {
delete lead[key];
}
});
return {
"rules": rules,
"leads": [lead]
};
}
/* ---------------------------------------------------------------------
* Integração com o ciclo de envio do Elementor
*
* 1. 'submit' → captura os valores ANTES do Elementor limpar o form.
* 2. 'submit_success' → só envia ao PipeRun se o Elementor validou e aceitou
* o envio (evita lead de form inválido / reCAPTCHA falho).
*
* Não usamos preventDefault: o Elementor cuida do envio, validação e mensagens.
* Handlers delegados no document funcionam também para forms em popups.
* ------------------------------------------------------------------- */
let pendingPayload = null;
$(document).on('submit', FORM_SELECTOR, function () {
pendingPayload = buildPayload($(this));
});
$(document).on('submit_success', FORM_SELECTOR, function () {
if (!pendingPayload || !pendingPayload.leads[0].email) {
console.warn('[PipeRun] Envio ignorado: payload ausente ou sem e-mail.');
return;
}
const dataToSend = pendingPayload;
pendingPayload = null;
$.ajax({
type: "POST",
url: ENDPOINT,
data: JSON.stringify(dataToSend),
dataType: "json",
success: function () {
trackConversion();
},
error: function (xhr, status, error) {
// O usuário já viu a mensagem de sucesso do Elementor; o lead fica
// salvo em Elementor &gt; Envios. Logamos para investigação.
console.error('[PipeRun] Falha ao enviar lead:', status, error, xhr.responseText);
}
});
});
</code></pre>
});
Pronto! Agora você já sabe como configurar a integração Json no CRM de Vendas PipeRun.
Em caso de dúvidas, chame nossa equipe no chat. 😉