Repository navigation
Landing pages
A landing is the page a visitor sees on the way to an offer. Orbitra serves four kinds, and the differences matter mostly for one question: how the buy button reaches the offer.
| Type | Where it lives | Offer link |
|---|---|---|
| Local | uploaded ZIP, served by the tracker |
{offer} or /?_lp=1
|
| Redirect | your own hosting, another domain |
/?_lp=1 + the JS adapter |
| Preload | fetched by the tracker, shown under your domain | {offer} |
| Action | nothing is shown; the tracker does something | — |
The archive is unpacked into landings/<landing id>/. The entry point is index.html, or index.php if PHP landings are enabled.
- The entry page must be named
index.html(orindex.php). - Use relative paths:
img/hero.jpg, not/img/hero.jpg. Both work, but relative paths also work when you open the archive locally. - No internal redirect to
index.html— the visitor would leave the tracked URL.
Unlike Keitaro, Orbitra does not add a <base> tag and does not rewrite your markup. The page is served byte for byte as you uploaded it, and its files are resolved against the landing you were shown. Two consequences worth knowing:
- A
<base>tag of your own is left alone. - Anchor links (
href="#form"), popup scripts and smooth scrolling keep working. In Keitaro these break, because it rewrites everyhref.
The simplest form, and the one to reach for:
<a href="{offer}">Buy</a>{offer} is replaced with the signed landing→offer transition (since 1.6.14, matching Keitaro): the click passes through the tracker, so the funnel is counted and the offer's macros are substituted at the redirect. Before 1.6.14 it embedded the advertiser's direct URL, which skipped the tracker — streams with "offer selection: before" showed zero clicks.
With several offers on one page, either form works — the explicit one in every version:
<a href="/?_lp=1&offer_id=10">Offer 10</a>
<a href="{offer}&offer_id=22">Offer 22</a> <!-- 1.6.14+ -->Appending &offer_id= to {offer} switches the offer (since 1.6.14): {offer} expands to the signed transition link, so the tracker reads the parameter and re-attributes the click — a conversion lands on the offer you named. Before 1.6.14 {offer} expanded to the advertiser's direct URL and the parameter was just passed along to them; the explicit /?_lp=1&offer_id=N form works in every version.
Passing a choice made on the landing (a product, plan or quiz answer) works the Keitaro way: add sub_id_1 … sub_id_30 to the transition link and they update the click.
<a href="/?_lp=1&sub_id_5=Blue%20Watch&sub_id_6=https%3A%2F%2Fcdn.example%2Fblue.jpg">Buy the blue one</a>The offer URL then picks them up as {sub_id_5} / {sub_id_6}, e.g. https://network.example/?sub1={clickid}&product={sub_id_5}&image={sub_id_6}. The values are written to the click too, so reports and postbacks see the same thing. Only sub_id_N keys are accepted, empty values never erase what the traffic source sent, and each value is capped at 512 bytes. On a landing hosted elsewhere, append them to the signed link: {lp_url}&sub_id_5=….
Since 1.6.14 {offer}&sub_id_5=… works too — the macro is the transition link itself, so the tracker reads what you append to it. If the value is known before the click (one product per campaign), skip the landing step entirely and put ?sub_id_5=… in the campaign link.
Nothing to add to the page: every landing the tracker serves gets a small timer
injected before </body>. It reports how long the visitor stayed — whether or
not they ever pressed the offer button, which is the difference between this
and Time to offer: a page nobody clicks through reports nothing under the
older metric, and that is precisely the page worth finding.
What it measures, and what it deliberately does not:
- only visible time — a tab left in the background does not accumulate;
- the deepest scroll reached, 0-100 %, alongside the seconds;
- checkpoints at 5, 15, 30 and 60 seconds and every minute after, plus a final flush when the page is hidden or unloaded, so a closed tab still leaves a number.
Where it shows up: the Time on LP column in Logs (values under 5 seconds are highlighted) and in the click details, and in reports as the Time on LP, LP bounce rate, LP scroll depth and LP measured visits metrics plus the Time on LP (bucket) dimension. A visit that never reported — a redirect landing on someone else's domain without the tracking script, a bot that runs no JS — groups as Unknown rather than being counted as a zero-second visit.
For a landing hosted elsewhere, the same timer ships inside
tracking.js / kclient.js; a PHP page echoes
$client->timerScript() (see Tracking Client (PHP)).
Substituted in the HTML of a local landing:
| Macro | Value |
|---|---|
{offer} |
signed landing→offer transition (/index.php?_lp=1&_token=…, since 1.6.14 — the click passes through the tracker, so the funnel counts and appended &offer_id= / &sub_id_N parameters reach it; same value as {lp_url}) |
{lp_url} |
the same signed transition, spelled for external landings |
{offer_id} |
the bound offer's id |
{clickid}, {subid}
|
the click id |
{token} |
signed token, used by the JS adapter |
{keyword}, {sub_id_1} … {sub_id_30}
|
click parameters captured from the traffic source |
Values taken from the URL are HTML-escaped. Nothing else is touched — {unknown}, JS template literals, Vue and Angular syntax all survive.
With no offer on the stream, {offer} becomes an unsigned transition link, which explains the misconfiguration when clicked instead of silently reloading the page.
The landing sits on your own hosting. The tracker sends the visitor there and appends two parameters:
https://your-landing.example/promo?_subid=<click id>&_token=<signed token>
The token is what makes the offer link work at all. A landing on another domain cannot read the tracker's cookies, so without it the tracker has no way to tell which click is coming back. It is signed with HMAC-SHA256 and expires after 24 hours; a bare _subid from the URL is not accepted on its own, because that would let anyone attribute a visit to any click id they like. A local or preload landing recovers the click from its cookie instead, so it does not need the token.
A {offer} inside the landing's own URL becomes the same transition, absolute (http://your-tracker/index.php?_lp=1&_token=…), so a landing that takes its CTA from a query parameter gets a working link too. Both behaviours need v1.6.14; before it the pair never actually arrived and {offer} embedded the advertiser's direct URL.
Install the JS adapter and link the offer as:
<a href="/?_lp=1">Buy</a>The adapter rewrites that into an absolute link to the tracker and adds _subid and _token.
The tracker fetches your page server-side, injects <base href> so its images and styles still load from the original host, applies macros and serves the result under your domain — no redirect. Use {offer} for the offer link.
Nothing is shown. Pick what happens:
| Action | Result |
|---|---|
| Send to campaign | hands the visitor to another campaign; the click counts in both |
| Show a 404 error | blank page, status 404 |
| Show as text | the text you enter, as text/plain
|
| Show as HTML | the HTML you enter |
| Do nothing | empty response; the visitor stays where they are |
{offer}, {clickid} and the click parameters are substituted in the text and HTML variants.
Keitaro passes the visitor to another campaign without a redirect. Orbitra uses a redirect: re-entering the tracker in the same request would mean including its entry script twice, which PHP cannot do. The click is recorded in both campaigns either way — the visitor just makes one extra hop.
<script src="https://your-tracker/js/orbitra-adapter.js"
data-postback="https://your-tracker/POSTBACK_KEY/postback"></script>Paste it into <head> on every page. The panel shows the snippet with your own key filled in, under the landing's settings.
Required for a redirect landing. Optional but useful for a local one with several pages: it carries the click onto inner pages and forms, so page two still knows who the visitor is.
It deliberately leaves alone what Keitaro's adapter rewrites: #anchors, mailto:, tel: and javascript: links are untouched, and links to third-party domains never receive your click id.
<a href="{offer}" onclick="orbitraPostback(this, event, 'lead', 10)">Buy</a>Arguments: the element, the event, a conversion status, an optional payout and an optional transaction id. Navigation proceeds even if the postback fails — losing the sale to a reporting hiccup would be the worse trade.
For a form handler, PHP is simpler:
file_get_contents('https://your-tracker/POSTBACK_KEY/postback?subid=' . urlencode($_COOKIE['subid']) . '&status=lead');Off by default. Turn them on in Settings → General → Allow PHP landings, and only for landings whose code you trust: a PHP landing runs inside the tracker, in the web root.
- The entry page is
index.php. - These calls are rejected at upload:
exec,system,shell_exec,passthru,proc_open,popen,pcntl_exec,pcntl_fork,dl,eval,assert,create_function,symlink,link,set_time_limit,ini_set,ini_alter. - Include other files by absolute path:
require_once dirname(__FILE__) . '/src/lib.php'; // right require_once 'src/lib.php'; // wrong
- Keep execution under the timeout (3 seconds by default, 9 maximum). Set timeouts on every curl call:
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3); curl_setopt($ch, CURLOPT_TIMEOUT, 3);
<?php
$clickId = $rawClick->get('click_id');
$keyword = $rawClick->get('keyword');
$offer = $rawClick->get('offer'); // the offer URL, same as {offer}$rawClick is read-only. To record a conversion, send a postback.
The scan is not a sandbox. It reads the uploaded source with PHP's own tokenizer, so it sees real calls rather than words in comments — but
$f = 'sys' . 'tem'; $f();defeats it, as it defeats the equivalent check in every other tracker. What actually contains the risk is that the feature is off by default, that only an admin can enable it, and thatdisable_functionsandopen_basedirin yourphp.iniapply to a landing exactly as they apply to everything else. Set them.
LeadForge 2.0 is Orbitra's built-in engine for analyzing, cleaning, and reseating landing page bundles onto target affiliate networks.
- Auto Mode: Automatically detects the source network from code signatures and maps form submissions to the target network.
-
Cross-Network Mode: Removes legacy network order handlers (
send.php,order.php,api.php), cleans out foreign tracking pixels/scripts, and installs the universal multi-network bridge. -
Raw Mode (Clone Patch): Strips foreign counters and scripts, injects the ClickID/SubID bridge and
{offer}macros without generating backend handlers.
When enabled, LeadForge injects orbitra_adapter.js, providing:
- 150 Country Rules: Exact national & international regex patterns, mobile operator prefix checks, and min/max length constraints.
-
Dynamic Country Switching: Automatically updates validation rules, length caps, and counter helpers when the user changes
<select name="country">. - Interactive Live Input Badges: Real-time counter showing digits entered and remaining (e.g. «3 cifre inserite, 7 mancanti» → «Numero complete»).
- Strict Unicode Name Validation: Real-time filtering preventing digits and spam symbols in customer names.
- Haptic Vibration Feedback: Vibrates mobile devices on invalid phone format attempts.
-
ClickID / SubID Bridge: Captures all incoming tracking parameters (
subid,click_id,sub1..sub5,utm_*,fbp,fbc, etc.) and hydrates form fields across multi-page funnels.
Generates a standalone, self-contained order handler supporting 10 CPA networks:
- Dr.Cash, Webvork (with SuperClient fallback), Lucky.online, KMA.biz, TerraLeads (with SHA1 checksum verification), Leadbit, LemonAD, Everad, Ezaff, and Custom Webhooks.
- Automated E.164 Normalization: Standardizes local phone numbers to international format with country prefix reconciliation.
-
CRM Dual Logging: Simultaneously dispatches the lead to the affiliate network and records a complete raw lead snapshot into the Orbitra CRM Vault (
orbitraCrmRecordLead//crm-ingest). -
Failsafe Local Logging: Appends leads to
leadforge.leads.logandorbitra_leads_backup.log.
Images and video do not load. Use relative paths. If they are correct and the page still comes up bare, check that you are opening the campaign URL rather than landings/<id>/index.html directly.
The buy button goes nowhere. The landing is probably still pointing at the advertiser directly — a landing copied from someone else's funnel keeps their affiliate link. Replace those hrefs with {offer}.
Landing transition failed: original click not found. A landing on another domain without the JS adapter, or a visitor with cookies disabled and no _token in the URL.
no offer attached to this stream. The stream has a landing but no offer. Add one, or leave the landing as the final page and drop the offer link.
A PHP landing shows "disabled on this tracker". The feature is off; see above.
Вики собирается из папки docs/ репозитория. Правки — через pull request в docs/.
Getting started
Traffic
- Campaigns & streams
- Cloaking
- Landing pages
- Tracking Client (PHP)
- PWA & Web Push
- PWA Funnel
- Content gallery
Conversions & money
Analytics
Infrastructure
Management
For developers