Pop & Push Integration Guide
For SSPs and publishers sending pop-under or push traffic to TensorBids. If you can read JSON you already know most of this — the rest is where the money moves.
Overview
| Pop-under | Push | |
|---|---|---|
| Request | OpenRTB 2.5 | OpenRTB 2.5 or plain GET |
| Response | OpenRTB bid, URL in adm | Push creative (title, images, click URL) |
| Billing | CPM per 1,000 events | CPC per click |
| No bid | 204 No Content | 204 No Content |
Pick your integration below — you only need to read the one you are implementing. Feed setup, error handling and reporting apply to both.
Feed setup
We issue a separate feed per integration. You will receive a FEED_ID,
a TOKEN, a REPORT_TOKEN and your bidder endpoint.
TOKEN authenticates your feed. REPORT_TOKEN is separate and is only
for the reporting API — it cannot be used to bid.
| Property | Value |
|---|---|
| Protocol | OpenRTB 2.5 |
| Method | POST (GET also available for push) |
| Format | JSON |
| Currency | USD |
| Auction | First-price |
| No bid | 204 No Content |
Your integration
Bid request
A standard OpenRTB request. Mark the impression as pop with
imp.ext.type and a 0×0 banner.
| Field | Description |
|---|---|
| imp.ext.type | Must be "pop" |
| imp.banner.w/h | Use 0 × 0 for pop |
| imp.bidfloor | Minimum CPM in USD |
| imp.bidfloorcur | Bid floor currency |
| site.domain | Publisher domain |
| site.page | Page the traffic originated on |
| device.ip | User IP |
| device.ua | User-Agent |
| user.id | Publisher-side user ID, when available |
device.ip and device.ua drive geo, device, OS and browser
targeting. Without them a campaign that targets any of those cannot bid on your traffic, so
omitting them costs you fill.
Bid response
A standard OpenRTB bid, with one important difference:
adm holds a URL, not HTML.
| Field | Description |
|---|---|
| price | CPM bid |
| adm | Pop destination / tracking URL |
| nurl | Win notification |
| adid / crid | Creative identifiers |
| cid | Campaign ID |
| adomain | Advertiser domain |
Open it exactly as returned. It records the event and then redirects the user to the advertiser's landing page.
Do not replace it with the advertiser URL, and do not wrap it in another redirect — either one breaks tracking, and untracked traffic cannot be paid for.
Billing
Pop is billed CPM — per thousand events.
A bid that is never served is never charged, and duplicate tracking calls are de-duplicated automatically — so a retry cannot cost you.
"price": 0.079 means $0.079 per click — not per 1,000
impressions. Impressions are tracked but never charged. This is the single most common
misreading of this integration, so it is worth pausing on.
Bid request
A standard OpenRTB request with a push object inside the
impression.
| Field | Description |
|---|---|
| bidfloor | Minimum CPC in USD |
| push.keyword | Keyword / topic |
| push.wmax | Maximum image width |
| push.hmax | Maximum image height |
| push.subId | Placement / sub ID |
Used for geo, device, OS and browser targeting. Omitting them narrows which campaigns can bid on your traffic.
Bid response
| Field | Description |
|---|---|
| price | CPC bid |
| title | Notification title |
| description | Notification body |
| iconUrl | Notification icon |
| imageUrl | Main image |
| clickUrl | Click tracking + redirect URL |
| impTracker | Impression tracking URL(s) |
Do not rewrite it or wrap it in another redirect.
Tracking & billing
| Event | What you do | Charged? |
|---|---|---|
| Impression | Fire every URL in impTracker | No |
| Click | Open clickUrl | Yes |
It costs you nothing — impressions are never charged — but it is what CTR and traffic-quality optimisation are computed from. Feeds that report impressions get bid on more accurately.
Duplicate clicks are de-duplicated automatically.
If you don't run OpenRTB, push can be integrated with a single GET request. The response is identical to the oRTB push response — same fields, same tracking, same CPC billing.
Required
| Parameter | Description |
|---|---|
| e | Feed ID |
| t | Feed token |
| ip | User IP |
| ua | User-Agent |
| bid | CPC floor |
| dmn | Publisher domain |
| wm / hm | Maximum image dimensions |
Everything else is optional. URL-encode values — pg and ua
especially, since both routinely contain characters that will otherwise truncate the query.
If you get 400, check the seven parameters above before anything else — that is
almost always the cause.
Response
Identical to the oRTB push response: fire every
impTracker, open clickUrl as-is, and you are billed per click.
No bid & errors
| Response | Meaning | What to do |
|---|---|---|
| 204 | No bid — nothing matched, or your floor was above every bid | Normal. Move on. |
| 400 | Malformed request, usually a missing required field | Check required params, then the JSON body |
| 200 | A bid | Serve it |
A 204 carries an empty body and is not an error — it is the expected answer
whenever no campaign wants the impression.
Reporting API
Reconcile traffic, clicks and revenue against your own numbers.
| Parameter | Required | Description |
|---|---|---|
| token | Yes | Your feed REPORT_TOKEN |
| fromDate | Yes | Start date, UTC |
| toDate | Yes | End date, UTC |
| groupBy | No | Comma-separated dimensions |
Maximum range 92 days per request.
Dimensions
Response
Every value inside Report is a JSON string, including the
numeric ones — cast before you do arithmetic on them.
When a range has no rows, Message is "No Data Found" and
Report is an empty array. That is a success, not an error.
Timezone
All reporting is UTC, with the day starting at 00:00 UTC.
Reconcile on UTC periods or your totals will disagree with ours by a few hours' traffic.
Quick reference
| Pop | Push | |
|---|---|---|
| Protocol | OpenRTB 2.5 | OpenRTB 2.5 / GET |
| Pricing | CPM | CPC |
| Request | OpenRTB + imp.ext.type=pop | OpenRTB + push object |
| Response | OpenRTB bid | Push creative |
| Creative | URL in adm | Title, description, images |
| Click URL | adm | clickUrl |
| Impression tracking | — | impTracker |
| No bid | 204 | 204 |
Pop — send OpenRTB, receive adm, open it as-is.
Push — send OpenRTB or GET, render the creative, fire
impTracker, use clickUrl for clicks.
Never rewrite or wrap a URL we return. That is the whole contract.
Questions, or a field that isn't behaving as documented? Reply to your integration thread and include a full request and response — that is almost always enough to resolve it in one round.