Copie o código JavaScript abaixo e cole no seu site. O script irá automaticamente:
Substitua site_unico_id no script por um identificador único para seu site:
SITE_ID: 'meu_site_exemplo', // Substitua por seu ID único
Cole o script antes do fechamento da tag </body> em todas as páginas que deseja monitorar.
/**
* SiteMetric - Script de Monitoramento de Audiência
* Implemente este script em seu site para começar a monitorar visitantes
*/
(function() {
'use strict';
const CONFIG = {
API_URL: 'https://seu-dominio.com/sitemetric/api/',
CHECK_INTERVAL: 60000,
SITE_ID: 'site_unico_id',
COOKIE_NAME: 'sitemetric_session'
};
let started = false;
function normalizeSiteId(value) {
return String(value || '').trim().replace(/^www\./i, '');
}
function normalizeApiBaseUrl(value) {
let url = String(value || '').trim();
if (!url) return '';
if (url.includes('track.php')) {
url = url.split('track.php')[0];
}
if (!url.endsWith('/')) url += '/';
return url;
}
function findCurrentScript() {
if (document.currentScript) return document.currentScript;
const scripts = Array.from(document.getElementsByTagName('script'));
for (let i = scripts.length - 1; i >= 0; i--) {
const src = scripts[i].getAttribute('src') || '';
if (src.includes('script.js')) return scripts[i];
}
return null;
}
function inferApiUrlFromScript() {
const scriptEl = findCurrentScript();
const src = scriptEl?.getAttribute('src') || '';
if (!src) return '';
try {
const u = new URL(src, window.location.href);
const path = u.pathname.replace(/script\.js$/i, '');
return `${u.origin}${path.endsWith('/') ? path : path + '/'}`;
} catch {
return '';
}
}
function isPlaceholderConfig() {
return (
!CONFIG.API_URL ||
CONFIG.API_URL.includes('seu-dominio.com') ||
!CONFIG.SITE_ID ||
CONFIG.SITE_ID === 'site_unico_id'
);
}
function applyConfig(options) {
const opts = options || {};
const apiBase = normalizeApiBaseUrl(opts.apiUrl || opts.apiBaseUrl || opts.apiURL || opts.api_base_url);
const siteId = normalizeSiteId(opts.siteId || opts.site_id || opts.domain);
const checkInterval = Number.isFinite(Number(opts.checkInterval)) ? Number(opts.checkInterval) : null;
if (apiBase) CONFIG.API_URL = apiBase;
if (siteId) CONFIG.SITE_ID = siteId;
if (checkInterval && checkInterval > 0) CONFIG.CHECK_INTERVAL = checkInterval;
}
function autoConfigureIfNeeded() {
if (!isPlaceholderConfig()) return;
const inferredApi = inferApiUrlFromScript();
if (inferredApi) CONFIG.API_URL = inferredApi;
if (!CONFIG.SITE_ID || CONFIG.SITE_ID === 'site_unico_id') {
CONFIG.SITE_ID = normalizeSiteId(window.location.hostname);
}
}
// Função para obter IP do visitante
async function getVisitorIP() {
try {
const response = await fetch('https://api.ipify.org?format=json');
const data = await response.json();
return data.ip;
} catch (error) {
console.warn('SiteMetric: Não foi possível obter IP externo, usando IP local');
return generateLocalIP();
}
}
// Função para gerar IP local caso não consiga obter o real
function generateLocalIP() {
return '192.168.' + Math.floor(Math.random() * 255) + '.' + Math.floor(Math.random() * 255);
}
// Função para obter dados do visitante
function getVisitorData() {
return {
userAgent: navigator.userAgent,
language: navigator.language,
screenResolution: screen.width + 'x' + screen.height,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
referrer: document.referrer || 'direct',
currentPage: window.location.href,
timestamp: new Date().toISOString()
};
}
// Função para criar/atualizar cookie de sessão
function setSessionCookie(sessionId) {
const expires = new Date();
expires.setTime(expires.getTime() + (30 * 60 * 1000)); // 30 minutos
document.cookie = CONFIG.COOKIE_NAME + '=' + sessionId + '; expires=' + expires.toUTCString() + '; path=/';
}
// Função para obter ID de sessão
function getSessionId() {
const cookies = document.cookie.split(';');
for (let cookie of cookies) {
const [name, value] = cookie.trim().split('=');
if (name === CONFIG.COOKIE_NAME) {
return value;
}
}
return null;
}
// Função para gerar ID de sessão único
function generateSessionId() {
return 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
}
// Função para obter link de pagamento configurado
async function getPaymentLink() {
try {
const response = await fetch(CONFIG.API_URL + 'pagamentos.php?action=configuracoes');
const data = await response.json();
return data.configuracoes?.link_pagamento || '#';
} catch (error) {
console.warn('SiteMetric: Não foi possível obter link de pagamento:', error);
return '#';
}
}
// Função para verificar status de pagamento e mostrar aviso se necessário
async function checkPaymentStatusAndShowWarning() {
try {
// Obter domínio atual
const dominio = window.location.hostname.replace('www.', '');
const response = await fetch(CONFIG.API_URL + 'pagamentos.php?action=verificar_status&dominio=' + dominio);
const data = await response.json();
if (data && data.status_detalhado) {
// Obter link de pagamento
const paymentLink = await getPaymentLink();
data.link_pagamento = paymentLink;
showPaymentWarning(data);
}
} catch (error) {
console.warn('SiteMetric: Não foi possível verificar status de pagamento:', error);
}
}
// Função para mostrar aviso de pagamento discreto
function showPaymentWarning(paymentData) {
// Verificar se já existe um aviso
if (document.getElementById('sitemetric-payment-warning')) {
return;
}
const warningDiv = document.createElement('div');
warningDiv.id = 'sitemetric-payment-warning';
let message = '';
let className = '';
if (paymentData.status_detalhado === 'vencendo') {
message = `⚠️ Sua assinatura vence em ${paymentData.dias_ate_vencimento} dia(s). <a href="#" onclick="window.open('${paymentData.link_pagamento || '#'}', '_blank')" style="color: #ff6b35;">Clique aqui para pagar</a>`;
className = 'sitemetric-warning-vencendo';
} else if (paymentData.status_detalhado === 'vencido') {
message = `⚠️ Assinatura vencida há ${paymentData.dias_atraso} dia(s). <a href="#" onclick="window.open('${paymentData.link_pagamento || '#'}', '_blank')" style="color: #ff6b35;">Pague agora para continuar</a>`;
className = 'sitemetric-warning-vencido';
}
if (message) {
warningDiv.className = 'sitemetric-payment-warning ' + className;
warningDiv.innerHTML = `
<div class="sitemetric-warning-content">
<span class="sitemetric-warning-text">${message}</span>
<button class="sitemetric-warning-close" onclick="this.parentElement.parentElement.remove()">×</button>
</div>
`;
// Adicionar estilos CSS
const style = document.createElement('style');
style.textContent = `
.sitemetric-payment-warning {
position: fixed;
bottom: 20px;
right: 20px;
background: #1a1a1a;
color: #ffffff;
padding: 12px 16px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
border: 1px solid #ff6b35;
max-width: 300px;
z-index: 9999;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-size: 14px;
line-height: 1.4;
animation: slideInRight 0.3s ease-out;
}
.sitemetric-warning-vencendo {
border-color: #ffc107;
}
.sitemetric-warning-vencido {
border-color: #dc3545;
}
.sitemetric-warning-content {
display: flex;
align-items: flex-start;
gap: 8px;
}
.sitemetric-warning-text {
flex: 1;
}
.sitemetric-warning-text a {
color: #ff6b35;
text-decoration: none;
font-weight: 500;
}
.sitemetric-warning-text a:hover {
text-decoration: underline;
}
.sitemetric-warning-close {
background: none;
border: none;
color: #ffffff;
font-size: 18px;
cursor: pointer;
padding: 0;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.7;
}
.sitemetric-warning-close:hover {
opacity: 1;
}
@keyframes slideInRight {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@media (max-width: 480px) {
.sitemetric-payment-warning {
bottom: 10px;
right: 10px;
left: 10px;
max-width: none;
}
}
`;
document.head.appendChild(style);
document.body.appendChild(warningDiv);
// Auto-remover após 10 segundos
setTimeout(() => {
if (warningDiv.parentElement) {
warningDiv.remove();
}
}, 10000);
}
}
// Função principal para registrar visita
async function registerVisit() {
try {
// Primeiro verificar status de pagamento
await checkPaymentStatusAndShowWarning();
const ip = await getVisitorIP();
const visitorData = getVisitorData();
let sessionId = getSessionId();
if (!sessionId) {
sessionId = generateSessionId();
setSessionCookie(sessionId);
}
const data = {
siteId: CONFIG.SITE_ID,
sessionId: sessionId,
ip: ip,
visitorData: visitorData,
timestamp: new Date().toISOString()
};
// Envia dados para o servidor
const response = await fetch(CONFIG.API_URL + 'track.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error('Erro ao enviar dados');
}
console.log('SiteMetric: Visita registrada com sucesso');
} catch (error) {
console.error('SiteMetric: Erro ao registrar visita:', error);
}
}
// Função para manter visitante online
async function keepAlive() {
try {
const sessionId = getSessionId();
if (!sessionId) return;
const response = await fetch(CONFIG.API_URL + 'keepalive.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
siteId: CONFIG.SITE_ID,
sessionId: sessionId,
timestamp: new Date().toISOString()
})
});
if (!response.ok) {
if (response.status === 404) {
await registerVisit();
return;
}
throw new Error('Erro ao manter sessão ativa');
}
console.log('SiteMetric: Sessão mantida ativa');
} catch (error) {
console.error('SiteMetric: Erro ao manter sessão ativa:', error);
}
}
// Inicialização
function startTracking() {
if (started) return;
started = true;
console.log('SiteMetric: Iniciando monitoramento...');
// Registra visita ao carregar a página
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', registerVisit);
} else {
registerVisit();
}
// Mantém sessão ativa a cada intervalo
setInterval(keepAlive, CONFIG.CHECK_INTERVAL);
// Atualiza atividade em eventos do usuário
['click', 'scroll', 'keypress'].forEach(event => {
document.addEventListener(event, () => {
clearTimeout(window.sitemetricActivityTimeout);
window.sitemetricActivityTimeout = setTimeout(keepAlive, 5000);
});
});
}
window.SiteMetric = window.SiteMetric || {};
window.SiteMetric.init = function(options) {
applyConfig(options);
autoConfigureIfNeeded();
if (isPlaceholderConfig()) {
console.warn('SiteMetric: Configuração inválida. Defina domain/siteId e apiUrl.');
return;
}
startTracking();
};
autoConfigureIfNeeded();
if (!isPlaceholderConfig()) {
startTracking();
}
})();