PubAdzo V2.Docs
Back to Dashboard

Grow Advertiser Integration Guide

Learn how to track clicks with dynamic macros, configure multi-event conversion milestones, and send authenticated postback callbacks with zero fraud.

Integration Overview

The PubAdzo V2 Grow platform connects your mobile apps, games, and web campaigns to verified publisher traffic. Our tracking architecture follows a high-performance, real-time Server-to-Server (S2S) conversion lifecycle:

1. User Clicks Offer

The user selects your offer on the Reward Wall. PubAdzo V2 creates a unique 26-character click_id (ULID) and redirects the user to your Tracking URL.

2. User Completes Action

The user installs your app, opens it, registers an account, or reaches a targeted milestone (e.g. Level 10, First Deposit) specified in your campaign setup.

3. S2S Postback Triggered

Your server or Mobile Measurement Partner (AppsFlyer, Adjust, Singular) fires a GET or POST callback to PubAdzo V2 with the click_id and event key.

4. Verification & Payout

PubAdzo V2 validates the security signature, records the conversion, deduces your campaign budget, and rewards the user/publisher.

1. Receiving Clicks & Macros

When configuring your campaign in PubAdzo V2 Grow, provide your Destination / Tracking URL (e.g. Google Play Store URL, Apple App Store URL, or Mobile Measurement Partner tracking link). You can embed dynamic macros directly into your URL template:

Macro Type Description Example Replaced Value
{click_id} string (ULID) Essential. Unique 26-character universally unique identifier generated per click. You must store this value and return it in your conversion postback. 01JNW9TYW8E9QMTXYZ01234567
{campaign_id} integer The unique numeric identifier of your campaign in PubAdzo V2. 42
{pub_id} or {publisher_id} integer The unique Offerwall / Publisher ID generating the click. 7
Automatic Fallback Mechanism:

If you accidentally omit {click_id} from your Tracking URL template, the PubAdzo V2 redirection engine automatically detects its absence and safely appends ?click_id={click_id} (or &click_id={click_id}) to your destination URL. This ensures you never lose click attribution!

Sample Tracking URL Templates
Google Play Store (Install Referrer):
Android / Play Store
https://play.google.com/store/apps/details?id=com.yourcompany.app&referrer=click_id%3D{click_id}%26campaign_id%3D{campaign_id}
AppsFlyer Tracking Link:
AppsFlyer MMP
https://app.appsflyer.com/com.yourcompany.app?pid=clipzaar&click_id={click_id}&c={campaign_id}
Website / Web App Registration:
Web URL
https://example.com/signup?click_id={click_id}&utm_source=clipzaar&utm_campaign={campaign_id}

2. Campaign Events & Milestones

PubAdzo V2 Grow supports both Single-Event and Multi-Event (Multi-Reward) campaigns. Each milestone is configured with its own unique event_id and CPA/CPI bid:

Single Event Campaign

Ideal for standard CPI or simple signups. The campaign contains 1 target event (e.g. install or signup). Once reported, the offer is marked as completed for that user.

Multi-Event Campaign

Ideal for mobile games and apps with retention funnels. You define sequential steps (e.g. install for $0.20, level_10 for $0.80, deposit for $5.00). Each event triggers its own postback.

Event ID Matching Rule:

In every postback callback you send, the event or event_id parameter must exactly match an event_id defined in your Campaign Events. If you send an unregistered event ID, the backend returns: {"status": "error", "message": "Invalid event_id or event."}.

3. Conversion Postback Specification

When a user completes an installation or milestone, your server or MMP must trigger the PubAdzo V2 Postback Callback URL. Both HTTP GET and HTTP POST (JSON, Form-Data, or Query String) are natively supported.

Callback Endpoint URL
GET / POST https://clipzaar.com/postback/callback
Request Parameters
Parameter Type Location Requirement Description
click_id string (ULID) Query / Body Required The 26-character unique click identifier received during user redirection.
event or event_id string Query / Body Required The event step identifier (e.g. install, registration, level_5). Must match one of your campaign events.
security_token string Query / Body / Header Method A (Recommended) Your campaign's private Security Token. Passed directly in the URL query string (e.g. ?security_token=...), in the POST request body, or via the X-Security-Token HTTP header.
signature string (32 hex) Query / Body Method B (Alternative) MD5 signature calculated as md5(click_id + security_token). Optional alternative if you prefer not to expose the raw token in the URL.
txid string Query / Body Optional External conversion / transaction UUID from your MMP or internal database. Used to block replay and duplicate conversion attempts.

4. Postback Implementation & Authentication

PubAdzo V2 Grow allows you to send postbacks using either Direct Token (Method A - Recommended) or an MD5 Signature (Method B):

Method A: Direct GET Postback with Security Token (Standard & Simplest) RECOMMENDED

This is the standard method used by advertisers, MMPs, and backend webhooks. Simply append your click_id, event, and security_token directly into the query string:

GET https://clipzaar.com/postback/callback?click_id={click_id}&event=install&security_token={CAMPAIGN_SECURITY_TOKEN}
Implementation Snippets (Method A - Direct Query)
JavaScript (Fetch / URLSearchParams)
// 1. Conversion credentials
const clickId = '01JNW9TYW8E9QMTXYZ01234567'; // Received during user redirection
const eventName = 'install';                  // Must match one of your campaign event IDs
const securityToken = 'your_campaign_security_token'; // From Campaign Details

// 2. Build URL query parameters
const queryParams = new URLSearchParams({
    click_id: clickId,
    event: eventName,
    security_token: securityToken
}).toString();

const baseUrl = 'https://clipzaar.com/postback/callback';
const postbackUrl = baseUrl.includes('?') ? `${baseUrl}&${queryParams}` : `${baseUrl}?${queryParams}`;

console.log(`[Grow Postback] Firing URL: ${postbackUrl}`);

// 3. Fire HTTP GET request
fetch(postbackUrl)
  .then(res => res.json())
  .then(data => {
    if (data.status === 'success') {
      console.log('Conversion recorded:', data.message);
    } else {
      console.error('Postback rejected:', data.message);
    }
  })
  .catch(err => {
    console.error('Connection failed:', err.message);
  });
PHP (cURL / file_get_contents)
<?php
// 1. Conversion credentials
$click_id = "01JNW9TYW8E9QMTXYZ01234567"; // Received during user redirection
$event = "install";                      // Must match one of campaign event IDs
$security_token = "your_campaign_security_token"; // From Campaign Details

// 2. Build query parameters
$queryParams = http_build_query([
    'click_id'       => $click_id,
    'event'          => $event,
    'security_token' => $security_token,
]);

$postbackUrl = "https://clipzaar.com/postback/callback?" . $queryParams;

// 3. Fire HTTP GET request
$response = file_get_contents($postbackUrl);
$result = json_decode($response, true);

if (($result['status'] ?? '') === 'success') {
    echo "Success: " . ($result['message'] ?? 'Conversion recorded');
} else {
    echo "Failed: " . ($result['message'] ?? 'Verification error');
}
?>
Python 3 (Requests)
import requests

click_id = '01JNW9TYW8E9QMTXYZ01234567'
event_name = 'install'
security_token = 'your_campaign_security_token'

# 1. Define query parameters
params = {
    'click_id': click_id,
    'event': event_name,
    'security_token': security_token,
}

url = 'https://clipzaar.com/postback/callback'

# 2. Fire GET request
try:
    response = requests.get(url, params=params, timeout=10)
    data = response.json()
    if data.get('status') == 'success':
        print('Conversion recorded:', data.get('message'))
    else:
        print('Postback rejected:', data.get('message'))
except requests.exceptions.RequestException as e:
    print('Connection error:', e)
cURL CLI
# Direct HTTP GET Query
curl -X GET "https://clipzaar.com/postback/callback?click_id=01JNW9TYW8E9QMTXYZ01234567&event=install&security_token=YOUR_SECURITY_TOKEN"

# Or HTTP POST with JSON body
curl -X POST "https://clipzaar.com/postback/callback" \
  -H "Content-Type: application/json" \
  -d '{"click_id": "01JNW9TYW8E9QMTXYZ01234567", "event": "install", "security_token": "YOUR_SECURITY_TOKEN"}'

# Or HTTP POST with X-Security-Token header
curl -X POST "https://clipzaar.com/postback/callback" \
  -H "Content-Type: application/json" \
  -H "X-Security-Token: YOUR_SECURITY_TOKEN" \
  -d '{"click_id": "01JNW9TYW8E9QMTXYZ01234567", "event": "install"}'
Method B: Cryptographic Signature (Optional / Advanced) ALTERNATIVE

If your security policies require not exposing the raw security token in URL queries or access logs, you can calculate an MD5 hash signature locally on your server:

signature = md5( click_id + security_token )
HTTP GET with Signature Example:
GET https://clipzaar.com/postback/callback?click_id={click_id}&event=install&signature={signature}

5. Response Codes & Errors

The PubAdzo V2 postback endpoint always responds with an HTTP 200 OK status code containing a structured JSON response object. Check the status field (success or error) to verify execution:

Success Response (HTTP 200)
{
  "status": "success",
  "message": "Conversion processed successfully."
}
Error Response (HTTP 200)
{
  "status": "error",
  "message": "Security verification failed."
}
Complete Error Dictionary (Exact Backend Logic)
Backend Message Cause Resolution
Missing click_id The request did not supply a click_id parameter in query string or body. Ensure your postback captures and passes the click_id value originally sent in the user's click redirect.
Missing event_id or event The request did not provide the event or event_id parameter. Pass the event name (e.g. event=install) corresponding to your campaign's target event.
Missing security_token or signature Neither security_token nor signature was included in the request. Provide either your raw token (security_token or X-Security-Token header) or the calculated MD5 signature.
Invalid click_id The click_id does not exist in the database (fake, expired, or test ID). Only postback real click IDs generated by PubAdzo V2 during offer clicks.
Security verification failed. The security token or MD5 signature does not match your campaign's private token. Verify that you are using the correct Campaign Security Token from your campaign overview and that the hash format is md5(click_id + token).
Campaign is not active. The campaign is currently in pending, paused, draft, or rejected state. Ensure your campaign has been reviewed and approved, and has not been manually paused in your dashboard.
Invalid event_id or event. The specified event ID does not exist under this campaign. Check the Campaign Events list in your campaign overview to ensure the event string matches your setup exactly (case-sensitive).
Campaign budget exhausted. The campaign has reached its total budget limit (spent >= total_budget). Add funds or increase the total campaign budget in your Grow dashboard to reactivate tracking.
Campaign daily budget reached. Conversions today have reached your configured daily spending cap. The campaign will automatically resume accepting conversions at midnight UTC, or you can raise your daily budget limit.
Campaign is in cooldown/hidden for this user. The user is currently in a cooldown period for this campaign. Normal behavior for campaigns with cooldown limits configured.
User has already completed this campaign. The user has completed the campaign the maximum number of times allowed by your availability setting. Prevents users from re-completing single-run campaigns. If you want repeat conversions, set availability to Repeatable.
Conversion for this event already logged previously. Duplicate postback attempt detected for this specific click_id and event (or duplicate txid). PubAdzo V2 automatically rejects replay attacks. Each event step can be converted once per click.

6. Testing, MMP Setup & Anti-Fraud

Follow this step-by-step procedure to test your postback integration before launching live traffic:

1
Locate Campaign Credentials:

Navigate to your campaign details page (Grow > Campaigns). Under the Integration Links section, copy your Click Tracking URL, Callback URL, and Security Encryption Token.

2
Generate a Test Click:

When you or a test user clicks your offer link on the offerwall, capture the generated click_id query parameter from the redirection URL.

3
Fire Postback & Verify Response:

Send your test HTTP postback via cURL or Postman. The server should return {"status":"success","message":"Conversion processed successfully."} and your campaign's conversion counter and spend metrics will increment in real time.

Mobile Measurement Partner (MMP) Integration

If you use an attribution partner such as AppsFlyer, Adjust, Singular, or Branch, configure their Server-to-Server (S2S) postback using the following template mappings:

MMP Tracking URL Parameter S2S Postback URL Template
AppsFlyer &click_id={click_id} https://clipzaar.com/postback/callback?click_id=(clickid)&event=(event-name)&security_token=YOUR_TOKEN
Adjust &s2s=1&click_id={click_id} https://clipzaar.com/postback/callback?click_id={click_id}&event={event_name}&security_token=YOUR_TOKEN
Singular &clki={click_id} https://clipzaar.com/postback/callback?click_id={clki}&event={EVENT_NAME}&security_token=YOUR_TOKEN

Anti-Fraud & Conversion Safeguards

  • Cryptographic Click Fingerprinting: Every click generates a unique 26-character ULID (click_id) tied to the campaign, IP, user-agent, and country. Fabricated or random IDs are rejected instantly.
  • Double-Conversion Deduplication: Each event step can be converted exactly once per click. Duplicate postback requests sending the same click_id and event are intercepted and denied to prevent double-spending your budget.
  • External Transaction ID (txid) Tracking: If provided, external transaction IDs are indexed and verified across the entire campaign to stop malicious replay attacks across different requests.
  • High-Throughput Processing: The callback endpoint runs on optimized non-blocking routes without artificial rate limits or throttling, ensuring high conversion spikes during marketing surges are processed instantaneously.

Offerwall Publisher Integration Guide

Learn how to fetch JSON feeds, bind reward widgets, and set up secure callback listeners with MD5/SHA256 HMAC signature verification.

Type A: Render Integration (Iframe / WebView)

The easiest way to integrate the PubAdzo V2 Reward Wall is to load the visual UI directly using an HTML <iframe> on websites, or in a WebView inside your native Android/iOS mobile application.

Integration URL Structure
URL https://clipzaar.com/offerwall/render?appid={your_offerwall_id}&user_id={your_unique_user_id}
HTML Iframe Example Code
HTML
<iframe src="https://clipzaar.com/offerwall/render?appid=1&user_id=test_player_1" width="100%" height="800px" style="border:none; border-radius:16px;"></iframe>

Type B: JSON API Feed Integration (For Custom / Native UI)

For native mobile apps (Android/iOS) or custom reward screens, you can programmatically fetch the offer feed as JSON. This allows you to construct a custom user interface using your own styling while tracking conversions correctly.

API Endpoint
GET https://clipzaar.com/api/v1/offerwall?appid={your_offerwall_id}&user_id={your_unique_user_id}
Query Parameter Type Status Description
appid integer Required Your Offerwall Application ID.
user_id string Required A unique ID matching the active user (used to track user progress and generate valid click redirect links).
type string Optional Filter campaigns by category, conversion steps, or user status:
  • game: Filter for game offers.
  • app: Filter for non-game app offers.
  • one_step: Single conversion step campaigns.
  • multiple_step: Multi-milestone campaigns.
  • once: One-time completion campaigns.
  • repeat: Repeatable campaigns.
  • ongoing: Campaigns user has clicked but not yet fully finished.
  • completed: Campaigns user has fully finished.
JSON Feed Output Example (HTTP 200)
JSON Response
{
  "status": "success",
  "offerwall": {
    "id": 1,
    "name": "My Android Offerwall",
    "currency": "Coins",
    "exchange_rate": 100
  },
  "offers": [
    {
      "campaign_id": 12,
      "name": "Fantasy Kingdom RPG",
      "description": "Install and reach Level 10 to earn coins.",
      "platform": "android",
      "reward_points": 120,
      "payout_usd": 1.2000,
      "category": "game",
      "category_label": "Game",
      "step_type": "multiple_step",
      "step_type_label": "Multiple Steps",
      "user_status": "available",
      "user_status_label": "Available",
      "completed_count": 0,
      "max_completions": 1,
      "availability": "once",
      "icon_url": "https://clipzaar.com/storage/campaigns/icons/fantasy.png",
      "banner_url": "https://clipzaar.com/storage/campaigns/banners/fantasy.png",
      "steps": [
        {
          "event_id": 24,
          "event_key": "install",
          "name": "Install and open app",
          "description": "Open game for the first time",
          "payout_usd": 0.5000,
          "points": 50,
          "completed": false
        },
        {
          "event_id": 25,
          "event_key": "level_10",
          "name": "Reach Level 10",
          "description": "Upgrade your kingdom to level 10",
          "payout_usd": 0.7000,
          "points": 70,
          "completed": false
        }
      ],
      "click_tracking_url": "https://clipzaar.com/offerwall/click?appid=1&campaign_id=12&user_id=test_player_1"
    }
  ]
}

Publisher Callback Macro Tags

When configuring your Postback URL inside the details screen, you can embed any of the following macros. We automatically resolve and bind parameters before triggering your endpoint.

Macro Tag Description Resolved Value Example
{user_id} The custom user identifier passed in the offerwall render link query parameter. test_player_1
{payout} The revenue payout earned by the publisher (formatted in USD, 4 decimals). 1.2000
{points} The virtual coins amount calculated based on your exchange rate and rounding settings. 1200
{offer_id} The unique identifier of the completed offer/campaign. 15
{offer_name} The title of the completed offer/campaign. Survey Completion
{event_id} The unique event identifier setup in Grow (e.g. install, signup, level5). install
{event_name} The display name of the completed event from the campaign. Install App
{transaction_id} The unique transaction / conversion identifier (ULID). 01J234567890ABCDEFGHJKMNPQ
{ip} The IP address of the user who completed the offer. 192.168.1.50
{signature} MD5 verification hash computed using your API Secret Key. 32-char hexadecimal hash
{sig} HMAC SHA256 secure hash signature computed using your API Secret Key. 64-char hexadecimal hash

Postback Signature Verification Codes

To authenticate postback callbacks, verify either the {signature} (MD5) or {sig} (HMAC-SHA256) signature query parameter on your server using your private API Secret Key.

How PubAdzo V2 Outgoing Postback URL is Compiled & Sent

Below is an example of a Publisher's Postback URL template containing macros, followed by the exact GET request compiled and executed by PubAdzo V2's backend:

Your Configured Template URL:
https://yourdomain.com/postback-listener?user={user_id}&payout={payout}&points={points}&offer_id={offer_id}&offer_name={offer_name}&event_id={event_id}&transaction_id={transaction_id}&ip={ip}&sig={sig}
Actual GET Request Triggered by PubAdzo V2 Backend:
GET https://yourdomain.com/postback-listener?user=test_player_1&payout=1.2000&points=1200&offer_id=15&offer_name=Survey+Completion&event_id=install&transaction_id=01J234567890ABCDEFGHJKMNPQ&ip=192.168.1.50&sig=5af1ab0f9...
Method A: MD5 Hashing Formula
signature = MD5( user_id + payout_formatted + api_secret_key )
* Note: Payout must be formatted to exactly 4 decimal places with a dot separator (e.g. "1.2000").
Method B: HMAC SHA256 Hashing Formula
sig = HMAC-SHA256( user_id + ":" + payout_formatted, api_secret_key )
* Note: Payout must be formatted to exactly 4 decimal places with a dot separator (e.g. "1.2000").
PHP Endpoint Script
<?php
// 1. Retrieve query parameters sent by PubAdzo V2
$userId        = isset($_GET['user_id'])        ? $_GET['user_id']        : '';
$payout        = isset($_GET['payout'])        ? $_GET['payout']        : '';
$points        = isset($_GET['points'])        ? $_GET['points']        : '';
$offerId       = isset($_GET['offer_id'])      ? $_GET['offer_id']      : '';
$offerName     = isset($_GET['offer_name'])    ? $_GET['offer_name']    : '';
$eventId       = isset($_GET['event_id'])      ? $_GET['event_id']      : ''; // e.g. install, signup, level5
$transactionId = isset($_GET['transaction_id'])? $_GET['transaction_id']: '';
$userIp        = isset($_GET['ip'])            ? $_GET['ip']            : '';
$receivedSig   = isset($_GET['sig'])           ? $_GET['sig']           : ''; // HMAC-SHA256
$receivedMd5   = isset($_GET['signature'])     ? $_GET['signature']     : ''; // MD5
 
// Your unique Offerwall API Secret Key
$apiSecretKey = "your_api_secret_key_here";
 
if (!$userId || !$payout) {
    http_response_code(400);
    echo json_encode(["status" => "error", "message" => "Missing required parameters"]);
    exit;
}
 
// Format payout exactly to 4 decimals with dot separator (e.g. "1.2000")
$payoutFormatted = number_format((float)$payout, 4, '.', '');
$isValid = false;
 
if ($receivedSig) {
    // Verify using HMAC-SHA256
    $dataString = $userId . ':' . $payoutFormatted;
    $expectedSig = hash_hmac('sha256', $dataString, $apiSecretKey);
    if (hash_equals($expectedSig, $receivedSig)) {
        $isValid = true;
    }
} elseif ($receivedMd5) {
    // Verify using MD5
    $dataString = $userId . $payoutFormatted . $apiSecretKey;
    $expectedMd5 = md5($dataString);
    if (hash_equals($expectedMd5, $receivedMd5)) {
        $isValid = true;
    }
}
 
if ($isValid) {
    // ----------------------------------------------------
    // TODO: Perform your database operations here:
    // 1. Log transaction $transactionId to prevent duplicate crediting.
    // 2. Award $points to user $userId for completing event $eventId of offer $offerName ($offerId).
    // ----------------------------------------------------
    
    header('Content-Type: application/json');
    echo json_encode(["status" => "success", "message" => "Callback processed"]);
} else {
    http_response_code(400);
    header('Content-Type: application/json');
    echo json_encode(["status" => "error", "message" => "Signature mismatch"]);
}
?>
Node.js Express Handler
const express = require('express');
const crypto = require('crypto');
const app = express();

app.get('/postback/listener', (req, res) => {
  const { user_id, payout, points, offer_id, offer_name, event_id, transaction_id, ip, sig, signature } = req.query;
  const apiSecretKey = 'your_api_secret_key_here';

  if (!user_id || !payout) {
    return res.status(400).json({ status: 'error', message: 'Missing parameters' });
  }

  // Format payout exactly to 4 decimals with dot separator
  const payoutFormatted = parseFloat(payout).toFixed(4);
  let isValid = false;

  if (sig) {
    // Verify using HMAC-SHA256
    const dataString = `${user_id}:${payoutFormatted}`;
    const expectedSig = crypto
      .createHmac('sha256', apiSecretKey)
      .update(dataString)
      .digest('hex');

    if (crypto.timingSafeEqual(Buffer.from(expectedSig), Buffer.from(sig))) {
      isValid = true;
    }
  } else if (signature) {
    // Verify using MD5
    const dataString = `${user_id}${payoutFormatted}${apiSecretKey}`;
    const expectedMd5 = crypto
      .createHash('md5')
      .update(dataString)
      .digest('hex');

    if (expectedMd5 === signature) {
      isValid = true;
    }
  }

  if (isValid) {
    // ----------------------------------------------------
    // TODO: Perform database queries here:
    // 1. Check if unique transaction_id has already been rewarded.
    // 2. Award user_id the designated points for event_id on offer_name (offer_id).
    // ----------------------------------------------------
    return res.status(200).json({ status: 'success', message: 'Callback processed' });
  } else {
    return res.status(400).json({ status: 'error', message: 'Signature mismatch' });
  }
});
Python Flask Route
import hmac
import hashlib
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/postback/listener', methods=['GET'])
def postback_listener():
    user_id = request.args.get('user_id')
    payout = request.args.get('payout')
    points = request.args.get('points')
    offer_id = request.args.get('offer_id')
    offer_name = request.args.get('offer_name')
    event_id = request.args.get('event_id') # e.g. install, signup, level5
    transaction_id = request.args.get('transaction_id')
    user_ip = request.args.get('ip')
    received_sig = request.args.get('sig')          # HMAC-SHA256
    received_md5 = request.args.get('signature')    # MD5

    if not user_id or not payout:
        return jsonify({'status': 'error', 'message': 'Missing parameters'}), 400

    api_secret_key = b'your_api_secret_key_here'
    
    # Format payout exactly to 4 decimal places
    payout_formatted = "{:.4f}".format(float(payout))
    is_valid = False

    if received_sig:
        # Verify using HMAC-SHA256
        data_string = f"{user_id}:{payout_formatted}".encode('utf-8')
        expected_sig = hmac.new(api_secret_key, data_string, hashlib.sha256).hexdigest()
        if hmac.compare_digest(expected_sig, received_sig):
            is_valid = True
            
    elif received_md5:
        # Verify using MD5
        raw_key = api_secret_key.decode('utf-8')
        data_string = f"{user_id}{payout_formatted}{raw_key}"
        expected_md5 = hashlib.md5(data_string.encode('utf-8')).hexdigest()
        if hmac.compare_digest(expected_md5, received_md5):
            is_valid = True

    if is_valid:
        # ----------------------------------------------------
        # TODO: Perform database queries here:
        # 1. Log transaction_id to prevent duplicate crediting.
        # 2. Credit the points to the user_id's account for completing offer_name.
        # ----------------------------------------------------
        return jsonify({'status': 'success', 'message': 'Callback processed'}), 200
    else:
        return jsonify({'status': 'error', 'message': 'Signature mismatch'}), 400

Publisher Rate Limiting & Callback Best Practices

  • Support High Volume Throughput: During high-traffic periods, your endpoint may receive sudden bursts of conversion callbacks. Ensure that your receiver URL either does not rate limit PubAdzo V2 server IP addresses or handles high-concurrency requests smoothly to avoid dropping authentic conversions.
  • Double-Spend Prevention: Always store and log unique transaction/conversion records on your database. If you receive a subsequent duplicate callback for an already rewarded completion, do not credit points again. Instead, respond immediately with a success message (e.g. {"status":"success"}) to prevent balance inflation while acknowledging our notification system.
  • IP Whitelisting (Optional): We highly recommend whitelisting the PubAdzo V2 tracking server's IP address on your web server configurations or cloud firewalls (like Cloudflare) to ensure only authentic requests can call your postback handler.