+ "jsCode": "const https = require('https');\nconst httpGet = (url) => new Promise((resolve, reject) => { https.get(url, (res) => { let d = ''; res.on('data', c => d += c); res.on('end', () => { try { resolve(JSON.parse(d)); } catch(e) { reject(e); } }); }).on('error', reject); });\nconst ctx = $('Calcular Datas').first().json;\nconst token = ctx.metaToken;\nconst datePreset = ctx.datePreset || 'last_7d';\nconst periodStart = ctx.periodStart;\nconst periodEnd = ctx.periodEnd;\nconst periodoLabel = ctx.periodoLabel || '\\u00faltimos 7 dias';\nconst phone = ctx.phone;\n\nconst clientMap = [\n { id: 'act_497795903676192', nome: 'Antonio Neto', type: 'lead' },\n { id: 'act_2493856707309984', nome: 'Gabriel Jacinto', type: 'lead' },\n { id: 'act_2145598605527232', nome: 'Dani Escudero', type: 'lead' },\n { id: 'act_929521557422139', nome: 'Agro', type: 'lead' },\n { id: 'act_544347952854095', nome: 'Escola de M\\u00fasica', type: 'lead' },\n { id: 'act_1509005182799187', nome: 'Panmalhas Assessoria T\\u00eaxtil', type: 'lead' },\n { id: 'act_2811791829124905', nome: 'GFiX Store', type: 'lead' },\n { id: 'act_5585082641598366', nome: 'Arte em Gelo', type: 'lead' },\n { id: 'act_738466861151636', nome: 'ITAG Tecnologia', type: 'lead' },\n { id: 'act_873195821346004', nome: 'Hi Dogz', type: 'purchase' },\n { id: 'act_1673012226810411', nome: 'Batata Bistr\\u00f4', type: 'purchase' },\n { id: 'act_1082397873705862', nome: 'Caribbean Bronze', type: 'lead' },\n { id: 'act_738280412237298', nome: 'Larissa Kelleter', type: 'lead' }\n];\n\nconst fmtMoney = (val) => {\n const n = parseFloat(val) || 0;\n const fixed = n.toFixed(2);\n const parts = fixed.split('.');\n parts[0] = parts[0].replace(/(\\d)(?=(\\d{3})+$)/g, '$1.');\n return parts[0] + ',' + parts[1];\n};\n\nconst fmtNum = (val) => {\n const n = parseInt(val) || 0;\n return String(n).replace(/(\\d)(?=(\\d{3})+$)/g, '$1.');\n};\n\nconst fmtBR = (dateStr) => {\n const d = new Date(dateStr + 'T12:00:00Z');\n return String(d.getUTCDate()).padStart(2, '0') + '/' + String(d.getUTCMonth() + 1).padStart(2, '0');\n};\n\nconst LEAD_ACTION = 'onsite_conversion.total_messaging_connection';\nconst fields = 'spend,impressions,clicks,actions,action_values';\n\nconst dateRange = periodStart === periodEnd\n ? '_\\ud83d\\udcc5 ' + fmtBR(periodStart) + ' (' + periodoLabel + ')_'\n : '_\\ud83d\\udcc5 ' + fmtBR(periodStart) + ' a ' + fmtBR(periodEnd) + ' (' + periodoLabel + ')_';\n\nconst results = [];\n\nfor (const client of clientMap) {\n try {\n const url = 'https://graph.facebook.com/v19.0/' + client.id + '/insights?date_preset=' + encodeURIComponent(datePreset) + '&fields=' + encodeURIComponent(fields) + '&level=campaign&access_token=' + token;\n const data = await httpGet(url);\n const campaigns = (data.data) || [];\n\n if (!campaigns.length) {\n results.push({ json: { phone: phone, output: '*' + client.nome.toUpperCase() + '*\\n\\n' + dateRange + '\\n\\n*Meta Ads*\\n\\n\\u274c Sem dados no per\\u00edodo.' } });\n continue;\n }\n\n let totalSpend = 0, totalImpressions = 0, totalClicks = 0;\n for (const c of campaigns) {\n totalSpend += parseFloat(c.spend || '0');\n totalImpressions += parseInt(c.impressions || '0');\n totalClicks += parseInt(c.clicks || '0');\n }\n\n let reportText;\n\n if (client.type === 'purchase') {\n let totalPurchases = 0, totalRevenue = 0;\n for (const c of campaigns) {\n const pa = (c.actions || []).find(a => a.action_type === 'purchase' || a.action_type === 'offsite_conversion.fb_pixel_purchase');\n if (pa) totalPurchases += parseInt(pa.value);\n const ra = (c.action_values || []).find(a => a.action_type === 'purchase' || a.action_type === 'offsite_conversion.fb_pixel_purchase');\n if (ra) totalRevenue += parseFloat(ra.value);\n }\n const cpp = totalPurchases > 0 ? totalSpend / totalPurchases : 0;\n reportText =\n '*' + client.nome.toUpperCase() + '*' + '\\n\\n' +\n dateRange + '\\n\\n' +\n '*Meta Ads*' + '\\n\\n' +\n 'Impress\\u00f5es: ' + fmtNum(totalImpressions) + '\\n\\n' +\n 'Cliques: ' + fmtNum(totalClicks) + '\\n\\n' +\n 'Vendas: ' + totalPurchases + '\\n\\n' +\n 'Faturamento: R$ ' + fmtMoney(totalRevenue) + '\\n\\n' +\n 'Custo por venda: R$ ' + fmtMoney(cpp) + '\\n\\n' +\n '*INVESTIMENTO TOTAL: R$ ' + fmtMoney(totalSpend) + '*';\n } else {\n // Leads = Novos contatos de mensagem (campanhas WhatsApp)\n let leadSpend = 0, totalLeads = 0;\n for (const c of campaigns) {\n const la = (c.actions || []).find(a => a.action_type === LEAD_ACTION);\n if (la) {\n leadSpend += parseFloat(c.spend || '0');\n totalLeads += parseInt(la.value);\n }\n }\n const cpl = totalLeads > 0 ? leadSpend / totalLeads : 0;\n reportText =\n '*' + client.nome.toUpperCase() + '*' + '\\n\\n' +\n dateRange + '\\n\\n' +\n '*Meta Ads*' + '\\n\\n' +\n 'Impress\\u00f5es: ' + fmtNum(totalImpressions) + '\\n\\n' +\n 'Cliques: ' + fmtNum(totalClicks) + '\\n\\n' +\n 'Leads: ' + totalLeads + '\\n\\n' +\n 'Custo por lead: R$ ' + fmtMoney(cpl) + '\\n\\n' +\n '*INVESTIMENTO TOTAL: R$ ' + fmtMoney(totalSpend) + '*';\n }\n\n results.push({ json: { phone: phone, output: reportText } });\n } catch(e) {\n results.push({ json: { phone: phone, output: '*' + client.nome.toUpperCase() + '*\\n\\n\\u274c Erro ao buscar dados: ' + e.message } });\n }\n}\n\nreturn results;"
0 commit comments