Pular para o conteúdo principal
Zenovay
Gratuito25 minutesAvançado

Rastreamento no Lado do Servidor

Envie eventos e visualizações de página diretamente ao endpoint de rastreamento do Zenovay a partir do seu servidor para imunidade contra bloqueadores de anúncios e controle total da coleta.

server-sideapitrackingbackendprivacy
Última atualização:

Envie eventos de análise diretamente do seu backend para o Zenovay. O rastreamento no lado do servidor é imune a bloqueadores de anúncios, permite que você registre eventos que ocorrem apenas no servidor (compras confirmadas, assinaturas orientadas por webhook) e oferece controle total sobre o que é enviado.

Por que o rastreamento no lado do servidor?

Benefícios

BenefícioDescrição
Imunidade a bloqueadores de anúnciosOs eventos chegam ao Zenovay mesmo quando o script do cliente está bloqueado pelo navegador
Eventos apenas do servidorRastreie coisas que ocorrem apenas no lado do servidor — pagamentos confirmados, jobs de cron, webhooks
Controle de dadosVocê decide exatamente o que é enviado
Rastreamento híbridoCombine com o script do cliente para cobertura completa

Quando usar

  • Confirmação de compra em comércio eletrônico (após confirmação do provedor de pagamento)
  • Eventos de backend (assinatura criada, assinatura cancelada)
  • Eventos acionados por webhook (Stripe, provedores de pagamento)
  • Rastreamento híbrido (script do cliente para navegação + servidor para conversões confirmadas)

Endpoint de rastreamento

As solicitações do lado do servidor usam o mesmo endpoint de ingestão que o script do cliente. Envie um POST ao endpoint de rastreamento com o código de rastreamento do seu site no caminho:

POST https://api.zenovay.com/e/{trackingCode}

Este é um endpoint público, não autenticado — não requer uma chave de API e está aberto em todos os planos (é o mesmo caminho para o qual o script de rastreamento envia). O código de rastreamento é o mesmo valor que você coloca no atributo data-tracking-code do seu snippet de instalação.

Informação

O endpoint de ingestão é compartilhado com o rastreador do navegador, portanto sua carga útil é estruturada como os dados que um navegador enviaria. Isso significa que alguns campos que o navegador preenche automaticamente — session_id, device_type, browser, os e user_agent — devem ser fornecidos por você no corpo JSON ao chamar a partir de um servidor. As solicitações que não têm esses campos são rejeitadas.

Campos obrigatórios

Cada evento que você enviar deve incluir esses campos no corpo JSON:

CampoNotas
session_idUma string de pelo menos 8 caracteres. Reutilize o mesmo valor para eventos que pertencem à mesma visita.
urlUma URL completa e válida (por exemplo https://example.com/checkout/success).
device_typepor exemplo desktop, mobile, tablet ou server.
browserUm nome de navegador/cliente. Use algo descritivo para tráfego de servidor (por exemplo server).
osUm nome de sistema operacional (por exemplo Linux).
user_agentUma string de user-agent. Evite agentes genéricos semelhantes a bots (curl, python, wget, etc.) — eles são filtrados como bots.

visitor_id é opcional, mas recomendado (≥8 caracteres) para que eventos repetidos se vinculem ao mesmo visitante.

Visualização de página vs. Evento personalizado

O tipo de evento é definido com o campo event_type:

  • Visualização de página — omita event_type (padrão) ou defina-o como pageview.
  • Evento personalizado — defina event_type para custom, coloque o nome do evento em event_name e quaisquer metadados em properties.
# Evento personalizado (por exemplo, uma compra confirmada)
curl -X POST "https://api.zenovay.com/e/YOUR_TRACKING_CODE" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "custom",
    "event_name": "purchase",
    "url": "https://example.com/checkout/success",
    "referrer": "https://example.com/cart",
    "session_id": "srv-9f2a7c41bd",
    "device_type": "server",
    "browser": "server",
    "os": "Linux",
    "user_agent": "MyApp-Server/1.0",
    "properties": {
      "order_id": "ORD-12345",
      "value": 99.99,
      "currency": "USD"
    }
  }'
# Visualização de página
curl -X POST "https://api.zenovay.com/e/YOUR_TRACKING_CODE" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "pageview",
    "url": "https://example.com/products/widget",
    "referrer": "https://google.com/search",
    "session_id": "srv-9f2a7c41bd",
    "device_type": "server",
    "browser": "server",
    "os": "Linux",
    "user_agent": "MyApp-Server/1.0"
  }'

Uma nota sobre a geolocalização

Para tráfego de navegador, o Zenovay obtém a localização do IP do visitante que se conecta. Quando você chama o endpoint do seu servidor, o IP que se conecta é o do seu servidor — portanto, os eventos serão geolocalizados para sua infraestrutura, não para o usuário final.

Se você precisar de geolocalização precisa por visitante, execute esse rastreamento no lado do cliente (o snippet de instalação padrão) ou use o proxy first-party, e reserve o rastreamento no lado do servidor para eventos de backend (compras, assinaturas) onde a localização exata do usuário não é o ponto. Adicionar um header X-Forwarded-For em uma chamada simples do servidor não sobrescreve o IP do servidor para o endpoint público.

Exemplos de implementação

Node.js / Express

// lib/analytics.js
const TRACKING_CODE = process.env.ZENOVAY_TRACKING_CODE;
const ENDPOINT = `https://api.zenovay.com/e/${TRACKING_CODE}`;

// Campos base que cada evento do lado do servidor precisa.
const SERVER_DEFAULTS = {
  device_type: 'server',
  browser: 'server',
  os: 'Linux',
  user_agent: 'MyApp-Server/1.0'
};

async function trackEvent(eventName, { url, sessionId, properties = {} }) {
  const payload = {
    event_type: 'custom',
    event_name: eventName,
    url,
    session_id: sessionId,
    properties,
    ...SERVER_DEFAULTS
  };

  try {
    const response = await fetch(ENDPOINT, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
    return response.ok;
  } catch (error) {
    console.error('Analytics error:', error);
    return false;
  }
}

async function trackPageview({ url, sessionId, referrer = '' }) {
  const payload = {
    event_type: 'pageview',
    url,
    referrer,
    session_id: sessionId,
    ...SERVER_DEFAULTS
  };

  try {
    const response = await fetch(ENDPOINT, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
    return response.ok;
  } catch (error) {
    console.error('Pageview tracking error:', error);
    return false;
  }
}

module.exports = { trackEvent, trackPageview };

Python (Flask)

# analytics.py
import os
import requests
from flask import request

TRACKING_CODE = os.getenv('ZENOVAY_TRACKING_CODE')
TRACKING_URL = f'https://api.zenovay.com/e/{TRACKING_CODE}'

SERVER_DEFAULTS = {
    'device_type': 'server',
    'browser': 'server',
    'os': 'Linux',
    'user_agent': 'MyApp-Server/1.0',
}

def track_event(event_name, session_id, url, properties=None):
    payload = {
        'event_type': 'custom',
        'event_name': event_name,
        'url': url,
        'session_id': session_id,
        'properties': properties or {},
        **SERVER_DEFAULTS,
    }
    try:
        response = requests.post(TRACKING_URL, json=payload, timeout=5)
        return response.ok
    except Exception as e:
        print(f'Analytics error: {e}')
        return False

def track_pageview(session_id, url, referrer=''):
    payload = {
        'event_type': 'pageview',
        'url': url,
        'referrer': referrer,
        'session_id': session_id,
        **SERVER_DEFAULTS,
    }
    try:
        response = requests.post(TRACKING_URL, json=payload, timeout=5)
        return response.ok
    except Exception as e:
        print(f'Pageview tracking error: {e}')
        return False

PHP

<?php
class ZenovayAnalytics {
    private $trackingUrl;
    private $defaults = [
        'device_type' => 'server',
        'browser'     => 'server',
        'os'          => 'Linux',
        'user_agent'  => 'MyApp-Server/1.0',
    ];

    public function __construct($trackingCode) {
        $this->trackingUrl = "https://api.zenovay.com/e/{$trackingCode}";
    }

    public function trackEvent($eventName, $sessionId, $url, $properties = []) {
        $payload = array_merge([
            'event_type' => 'custom',
            'event_name' => $eventName,
            'url'        => $url,
            'session_id' => $sessionId,
            'properties' => $properties,
        ], $this->defaults);
        return $this->sendRequest($payload);
    }

    public function trackPageview($sessionId, $url, $referrer = '') {
        $payload = array_merge([
            'event_type' => 'pageview',
            'url'        => $url,
            'referrer'   => $referrer,
            'session_id' => $sessionId,
        ], $this->defaults);
        return $this->sendRequest($payload);
    }

    private function sendRequest($payload) {
        $ch = curl_init($this->trackingUrl);
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($payload),
            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 5
        ]);
        curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return $httpCode >= 200 && $httpCode < 300;
    }
}

// Uso
$analytics = new ZenovayAnalytics(getenv('ZENOVAY_TRACKING_CODE'));
$analytics->trackEvent('purchase', 'srv-9f2a7c41bd', 'https://example.com/checkout/success', [
    'order_id' => 'ORD-12345',
    'value'    => 99.99
]);

Rastreamento híbrido

O padrão mais comum: rastreie a navegação com o script do cliente e confirme conversões do servidor assim que o provedor de pagamento as confirmar.

// Lado do cliente: rastreie a intenção usando o script Zenovay
window.zenovay('track', 'checkout_started');

// Lado do servidor: rastreie o evento confirmado de seu manipulador de webhook
app.post('/webhooks/stripe', async (req, res) => {
  const event = req.body;

  if (event.type === 'checkout.session.completed') {
    await trackEvent('purchase', {
      url: 'https://example.com/checkout/success',
      sessionId: 'srv-' + event.data.object.id.slice(-12),
      properties: {
        order_id: event.data.object.id,
        value: event.data.object.amount_total / 100
      }
    });
  }

  res.sendStatus(200);
});

Filtragem de bots

O Zenovay já filtra tráfego de bot óbvio no lado da ingestão, portanto eventos enviados com agentes genéricos como curl, wget, python ou qualquer coisa que corresponda a padrões comuns de crawler são rejeitados. É por isso que os exemplos acima usam um user_agent descritivo para seu servidor.

Se você também encaminhar solicitações de cliente reais através do seu backend, filtre crawlers antes de enviar para não queimar seu limite de taxa em tráfego que seria rejeitado de qualquer forma:

function isBot(userAgent) {
  const botPatterns = [
    /bot/i, /crawler/i, /spider/i, /scraper/i,
    /curl/i, /wget/i, /python/i, /java\//i,
    /googlebot/i, /bingbot/i, /yandex/i
  ];
  return botPatterns.some(pattern => pattern.test(userAgent || ''));
}

Limites de taxa

O endpoint de rastreamento tem limites de taxa por endereço IP:

  • Limite de rajada: 60 requisições por 10 segundos
  • Limite sustentado: 5.000 requisições por hora

Esses limites se aplicam especificamente ao endpoint de ingestão de rastreamento, não à API REST (que é um recurso pago separado com seus próprios limites).

Solução de problemas

Os eventos não aparecem

Verifique:

  • O código de rastreamento no caminho da URL está correto.
  • Todos os campos obrigatórios estão presentes (session_id de 8+ caracteres, url válida, device_type, browser, os, user_agent). Campos ausentes retornam um 400 com uma lista do que está faltando.
  • Seu user_agent não está sendo filtrado como um bot (evite curl, python, etc.).
  • O IP não tem limite de taxa.

Eventos duplicados

Certifique-se:

  • Você não está rastreando o mesmo evento tanto do lado do cliente quanto do servidor.
  • Os manipuladores de webhook não estão disparando mais de uma vez para o mesmo evento.

A geolocalização reflete seu servidor

Isso é esperado para chamadas do lado do servidor — o IP que se conecta é seu servidor, não o visitante. Use o script do cliente (ou um proxy first-party) para geolocalização precisa do visitante e use o rastreamento no lado do servidor para eventos de backend onde a localização não é o objetivo.

Próximos passos

Este artigo foi útil?