External Landing Tracking API
Use the external landing tracking API when your landing pages are hosted outside the tracker, but you still want Bangi CPA Tracker to record clicks, leads, and postbacks in one campaign report.
This setup is useful when the tracker dashboard and campaign data stay on one server, but landing pages are placed closer to traffic sources. For example, you can keep the tracker on a server in Europe and host landing pages in Latin America, Asia, Australia, or North America to reduce page load time for visitors in those regions.
This integration requires coding skills. A developer must add request handling to the landing page, generate or preserve a click ID, and call the tracker endpoints at the right moments.
How It Works
The tracker needs one shared value across the whole visitor journey: clickId.
Think of clickId as the receipt number for a visitor. The click endpoint creates the receipt. The lead and postback endpoints add later events to that same receipt.
Endpoint Summary
| Endpoint | Method | Required fields | Main purpose |
|---|---|---|---|
/api/v2/track/click |
POST JSON |
clickId, campaignId |
Records that a visitor reached the external landing page. |
/api/v2/track/lead |
GET query or POST JSON |
clickId |
Records a lead event from the external landing page. |
/api/v2/track/postback |
GET query or POST JSON |
clickId |
Records a conversion or status update from an external system. |
All three endpoints accept extra parameters. The tracker stores those extra parameters with the event, so you can pass values such as ad names, offer IDs, traffic source IDs, statuses, or payout information.
Prerequisites
Before you start, prepare these items.
| Requirement | Description |
|---|---|
| Tracker API URL | The public HTTPS URL where the tracker API is available, for example https://dashboard.<your-domain>. |
| Campaign ID | The numeric tracker campaign ID that should receive these events. |
| External landing hosting | A server or hosting platform where your landing page code can make HTTP requests. |
| Developer access | Ability to edit landing page code and, if needed, advertiser or affiliate network postback settings. |
| Click ID storage | A way to keep the same clickId during the visitor session, such as a URL parameter, cookie, hidden form field, or server-side session. |
Step 1: Generate a Click ID
Generate one UUID for each visitor session before calling the click endpoint.
Example:
8f1b5c6e-7a3d-4d20-a7f1-12a2b8f7a9c1
Use the same value for all later events from that visitor journey.
Common ways to keep clickId available:
| Method | Use when |
|---|---|
| URL parameter | You redirect the visitor between pages and can append clickId to links. |
| Cookie | The visitor stays in the same browser session on your landing domain. |
| Hidden form field | A lead form must submit the same clickId to your backend. |
| Server-side session | Your backend controls the visitor session and event calls. |
Step 2: Track the Click
Call /api/v2/track/click when the visitor reaches the external landing page.
POST /api/v2/track/click HTTP/1.1
Host: dashboard.<your-domain>
Content-Type: application/json
{
"clickId": "8f1b5c6e-7a3d-4d20-a7f1-12a2b8f7a9c1",
"campaignId": 42,
"source": "facebook",
"campaign_name": "LatAm Ring Campaign",
"adset_name": "MX Android",
"ad_name": "video-01"
}
Expected response:
201 Created
clickId must be a UUID. campaignId must be the numeric ID of the campaign in the tracker.
Extra fields are optional. Use them for reporting context that you want to see later with the click.
Step 3: Track a Lead
Call /api/v2/track/lead when the visitor submits a form or completes the lead action on your external landing page.
GET example:
https://dashboard.<your-domain>/api/v2/track/lead?clickId=8f1b5c6e-7a3d-4d20-a7f1-12a2b8f7a9c1&offer_id=456&source=landing
POST example:
POST /api/v2/track/lead HTTP/1.1
Host: dashboard.<your-domain>
Content-Type: application/json
{
"clickId": "8f1b5c6e-7a3d-4d20-a7f1-12a2b8f7a9c1",
"offer_id": "456",
"source": "landing"
}
Expected response:
201 Created
Use this endpoint for events that happen directly on the external landing page, such as form submission. The tracker stores the lead event and its extra parameters.
Step 4: Track a Postback
Configure an advertiser, affiliate network, CRM, or another external system to report a conversion or status update to /api/v2/track/postback.
GET example:
https://dashboard.<your-domain>/api/v2/track/postback?clickId=8f1b5c6e-7a3d-4d20-a7f1-12a2b8f7a9c1&status=approved&payout=10&offer_id=456
POST example:
POST /api/v2/track/postback HTTP/1.1
Host: dashboard.<your-domain>
Content-Type: application/json
{
"clickId": "8f1b5c6e-7a3d-4d20-a7f1-12a2b8f7a9c1",
"status": "approved",
"payout": 10,
"offer_id": "456"
}
Expected response:
201 Created
If the campaign has a Status Mapper, the tracker uses the postback parameters to map the external status into one of the internal lead statuses: accept, expect, reject, or trash.
For example, if the campaign status mapper reads the status parameter, this postback:
status=approved
can become:
accept
Accepted and expected postbacks can also use the campaign cost value and currency for reporting.
Example Integration Flow
Use this checklist as the implementation order.
- Create or select a campaign in the tracker.
- Copy the campaign ID from the tracker.
- Add UUID generation to the external landing page backend.
- Store
clickIdfor the visitor session. - Call
POST /api/v2/track/clickwhen the landing page is opened. - Include the same
clickIdin the lead form submission. - Call
/api/v2/track/leadafter the lead form is submitted. - Pass the same
clickIdto the advertiser or affiliate network if they need to send postbacks. - Configure the advertiser or affiliate network postback URL to call
/api/v2/track/postback. - Open tracker reports and verify that clicks, leads, and postbacks appear for the campaign.
Implementation Notes
- Use HTTPS for all tracker API calls.
- Generate a new
clickIdfor each visitor journey, not one shared value for all visitors. - Keep the exact same
clickIdthrough click, lead, and postback events. - Send
clickIdin camelCase. The API expectsclickId, notclick_id. - Send
campaignIdin camelCase for click tracking. The API expectscampaignId, notcampaign_id. - Use
POST /api/v2/track/clickfor clicks. The click endpoint does not accept GET requests. - Use GET postbacks only when the external system cannot send JSON POST requests.
- Treat extra parameters as event metadata. The tracker stores them, but only configured status mapping controls internal conversion status.
Troubleshooting
| Problem | Likely cause | What to check |
|---|---|---|
| Click is not recorded | Missing or invalid clickId, missing campaignId, wrong API URL, or non-POST request |
Confirm the request is POST JSON and returns 201 Created. |
| Lead appears without campaign reporting context | The lead used a clickId that was never recorded by the click endpoint |
Confirm the click event is created before the lead event. |
Postback status becomes trash |
Campaign status mapper does not match the incoming parameter or value | Check the campaign Status Mapper parameter name and mapping values. |
| Postback has no payout or currency | The postback could not be connected to a campaign, or the mapped status is not accept or expect |
Confirm the same clickId exists in a click for the campaign. |
| GET request stores numbers as strings | Query string values are text | Use JSON POST if preserving JSON types matters for your integration. |
PHP Landing Example
Different landing pages can use different code. The examples below show one practical PHP implementation for developers who are comfortable editing PHP landings and submit.php handlers. Adapt the field names, CPA network request, validation, and error handling to your own landing page.
Track the Click
The example below records a click from a PHP landing page. It copies the current landing page query parameters, adds clickId and campaignId, sends the click event to the tracker, and returns the generated clickId so the landing page can reuse it for lead and postback tracking.
Replace these values before using the example:
| Value | Replace with |
|---|---|
https://dashboard.<your-domain> |
Your tracker dashboard/API domain |
1 |
The tracker campaign ID |
<?php
function generate_click_id()
{
$click_id = @file_get_contents('/proc/sys/kernel/random/uuid');
if (!$click_id) {
exec('uuidgen', $output);
$click_id = $output[0];
}
return trim($click_id);
}
function send_json_request($url, $payload)
{
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 2,
]);
curl_exec($ch);
curl_close($ch);
}
function track_click()
{
$query_string = ! empty($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
parse_str($query_string, $parameters);
$parameters['clickId'] = generate_click_id();
$parameters['campaignId'] = 1;
send_json_request(
'https://dashboard.<your-domain>/api/v2/track/click',
$parameters
);
return $parameters['clickId'];
}
$click_id = track_click();
Pass the Click ID Through the Form
After the click is tracked, pass $click_id with the order form. In this example, the value is sent as sub1, because many CPA networks support sub-parameters such as sub1, sub2, or similar fields.
<form id="order_form" action="submit.php?<?php echo http_build_query($_GET); ?>" method="post">
<!-- ... -->
<input type="hidden" name="sub1" value="<?php echo $click_id; ?>" />
<!-- ... -->
</form>
The same submitted form can be used for two actions:
- Send the order data to the CPA network with your normal CURL integration.
- Send a lead event to Bangi CPA Tracker with the same click ID.
Track the Lead from submit.php
In submit.php, read the click ID from the hidden sub1 field and send it to /api/v2/track/lead as clickId.
<?php
// ...
$track_lead_parameters = array_merge($order, [
'clickId' => $_POST['sub1'],
]);
send_json_request(
'https://dashboard.<your-domain>/api/v2/track/lead',
$track_lead_parameters
);
If submit.php is a separate file, define send_json_request() there too, or move it into a shared PHP file and include it from both the landing page and submit.php.
The $order array should contain the lead or order fields that are useful for your reports, such as offer ID, landing name, buyer status, phone country, or CPA network response data. Do not send sensitive personal data unless you intentionally want it stored in tracker event metadata.
You can still send $_POST or a prepared order payload to the CPA network with CURL. The important part is that the tracker lead call receives the same click ID that was created during click tracking.
For a complete path, keep the same value in all places:
| Place | Field name in this example | Purpose |
|---|---|---|
| Bangi click tracking | clickId |
Creates the tracked click. |
| Landing form | sub1 |
Carries the click ID through form submission. |
| CPA network request | sub1 |
Allows the network to return the click ID later in a postback. |
| Bangi lead tracking | clickId |
Connects the lead to the original click. |
| Bangi postback tracking | clickId |
Connects network conversion updates to the original click. |
After implementation, test the full path with one real browser session and one test lead. A clean test should produce one click event and the related lead or postback under the same clickId.