# BidMachine Developer Docs
> Guides and references for BidMachine SDK, Reporting API, and more
This file contains all documentation content in a single document following the llmstxt.org standard.
## BidMachine Placement Management API
import ApiLogo from "@theme/ApiLogo";
import Heading from "@theme/Heading";
import SchemaTabs from "@theme/SchemaTabs";
import TabItem from "@theme/TabItem";
import Export from "@theme/ApiExplorer/Export";
This API lets publishers create, list, update, and delete placements on their ad sources programmatically — without using the BidMachine dashboard. Requirements:
- Bearer token authentication. Obtain a token via the __Get Access Token__ endpoint using
your dashboard __login and password__.
- All operations are scoped to sources owned by the authenticated publisher.
Requests for foreign sources return **403 Forbidden**.
Note:
Tokens are short-lived. When a request returns **401 Unauthorized**, re-authenticate
and retry with a fresh token.
Security Scheme Type:
http
HTTP Authorization Scheme:
basic
Security Scheme Type:
http
HTTP Authorization Scheme:
bearer
---
## BidMachine Reporting API
import ApiLogo from "@theme/ApiLogo";
import Heading from "@theme/Heading";
import SchemaTabs from "@theme/SchemaTabs";
import TabItem from "@theme/TabItem";
import Export from "@theme/ApiExplorer/Export";
This API provides reporting data. Requirements:
- Basic Authentication (__login and password__).
- The maximum allowed time period for a query is **45 days** (the P2P Revenue report allows up to **2 years**).
- Rate limit: **6 requests per minute**.
Note:
Report generation can take between **10** to **60 seconds** depending on server load,
and the request timeout can be up to **300 seconds**.
Security Scheme Type:
http
HTTP Authorization Scheme:
basic
---
## Create Placement
import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint";
import ParamsDetails from "@theme/ParamsDetails";
import RequestSchema from "@theme/RequestSchema";
import StatusCodes from "@theme/StatusCodes";
import OperationTabs from "@theme/OperationTabs";
import TabItem from "@theme/TabItem";
import Heading from "@theme/Heading";
Creates a new placement on the given source. The placement `id` is generated server-side from the `name` and `bundle` fields — store it, you will need it for update and delete calls.
---
## Delete Placement
import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint";
import ParamsDetails from "@theme/ParamsDetails";
import RequestSchema from "@theme/RequestSchema";
import StatusCodes from "@theme/StatusCodes";
import OperationTabs from "@theme/OperationTabs";
import TabItem from "@theme/TabItem";
import Heading from "@theme/Heading";
Deletes the placement with the given `id` from the source.
---
## Get Access Token
import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint";
import ParamsDetails from "@theme/ParamsDetails";
import RequestSchema from "@theme/RequestSchema";
import StatusCodes from "@theme/StatusCodes";
import OperationTabs from "@theme/OperationTabs";
import TabItem from "@theme/TabItem";
import Heading from "@theme/Heading";
Returns a short-lived bearer token. Authenticate with HTTP Basic credentials — the same username and password used to log in to the dashboard. Use the returned token in all subsequent requests as `Authorization: Bearer `.
---
## List Placements
import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint";
import ParamsDetails from "@theme/ParamsDetails";
import RequestSchema from "@theme/RequestSchema";
import StatusCodes from "@theme/StatusCodes";
import OperationTabs from "@theme/OperationTabs";
import TabItem from "@theme/TabItem";
import Heading from "@theme/Heading";
Returns all placements for the given source.
---
## Retrieve Bidder Report Data
import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint";
import ParamsDetails from "@theme/ParamsDetails";
import RequestSchema from "@theme/RequestSchema";
import StatusCodes from "@theme/StatusCodes";
import OperationTabs from "@theme/OperationTabs";
import TabItem from "@theme/TabItem";
import Heading from "@theme/Heading";
Returns bidder reporting data in __NDJSON__ or __CSV__ format based on the query parameters. The endpoint accepts an interval, an optional output format, and an optional list of fields (dimensions) to be returned.
---
## Retrieve P2P Revenue Report Data
import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint";
import ParamsDetails from "@theme/ParamsDetails";
import RequestSchema from "@theme/RequestSchema";
import StatusCodes from "@theme/StatusCodes";
import OperationTabs from "@theme/OperationTabs";
import TabItem from "@theme/TabItem";
import Heading from "@theme/Heading";
Returns P2P revenue reporting data in __NDJSON__ or __CSV__ format based on the query parameters. The endpoint accepts a date range, an optional output format, header preferences for CSV, and an optional list of fields (dimensions) to be returned. The maximum allowed time period for this report is **2 years**.
---
## Retrieve SSP Report Data
import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint";
import ParamsDetails from "@theme/ParamsDetails";
import RequestSchema from "@theme/RequestSchema";
import StatusCodes from "@theme/StatusCodes";
import OperationTabs from "@theme/OperationTabs";
import TabItem from "@theme/TabItem";
import Heading from "@theme/Heading";
Returns reporting data in __NDJSON__ or __CSV__ format based on the query parameters. The endpoint accepts a date range, an optional output format, header preferences for CSV, and an optional list of fields (dimensions) to be returned.
---
## Update Placement
import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint";
import ParamsDetails from "@theme/ParamsDetails";
import RequestSchema from "@theme/RequestSchema";
import StatusCodes from "@theme/StatusCodes";
import OperationTabs from "@theme/OperationTabs";
import TabItem from "@theme/TabItem";
import Heading from "@theme/Heading";
Updates an existing placement. Send the full placement object including its `id` — all fields are replaced.
---
## Advanced Reporting
The BidMachine data reports provide insights into your ad performance, including metrics such as ad requests, impressions, CPM, and revenue, categorized by application and ad type levels.
You can access these reports in the **Reports** section of the BidMachine Publisher platform. There are two report types: **Ad Request Report** and **Impressions Report**.
## Ad Request Report
**Dimensions**
- `Time`
- `Ad Placement Type`
- `Device OS`
- `Region`
- `Source ID`
- `Source`
- `Datacenter`
- `Mediation Stack ID`
- `Test Mode`
**Metrics**
- `Ad Requests`
- `Unique Devices`
## Impressions Report
**Dimensions**
- `Time`
- `Ad Size`
- `Ad Type`
- `Adomain`
- `DSP Name`
- `App Bundle`
- `App Name`
- `App Version`
- `Bid Floor Level`
- `Bid Price Level`
- `Campaign ID`
- `Country`
**Metrics**
- `Impressions`
- `Publisher Revenue`
- `Publisher eCPM`
- `Unique Devices`
---
## Blocking Rules
import Image from '@theme/IdealImage'
Blocking Rules let you prevent unwanted ads from appearing in your app. You can block:
- Ad categories
- Advertising domains
- Bid bundles
- Creative IDs
**How to apply Blocking Rules?**
1. In the BidMachine dashboard, go to **Source & Blocking Rules**.
2. Click **Add** under the Blocking Rules section.
3. Enter bundle names in the **Apps** field to target specific applications.
4. Leave the **Apps** field empty to apply the rule to all apps.
---
## Creatives Preview
import Image from '@theme/IdealImage'
Creatives enable you to assess the ads displayed on your app, allowing you to review whether these creatives should remain active or be blocked.
You can access the Creative Review within the Creatives section of the BidMachine publisher platform.
To review a specific creative, please apply filters using both the CID and CRID.
To block the creative, navigate to the 'Blocking Rules' section at the Source level.
---
## Payments
import Image from '@theme/IdealImage'
## Payments Overview
To ensure timely payment, complete your payment details in the BidMachine dashboard.
1. Log in and navigate to the **Payments** page.
2. Click **Payment Details**.
3. Fill out your payment information and click **Save**.
## Payments History
On the **Payments History** tab, you can review past payments. Each payment displays one of three statuses:
- **Pending**: Created and being processed by our Financial team (up to 5 days).
- **Completed**: Successfully sent to your bank account.
- **Rejected**: Failed due to incorrect details or a bank issue. We will contact you to update your information or resolve the issue.
:::tip Minimum Payable Amount
The minimum payable amount is **$1,000**. If your monthly earnings are below this threshold, the balance rolls over to the next month.
If you decide to close your account before reaching $1,000, email [support@bidmachine.io](mailto:support@bidmachine.io) to request payment of your remaining balance.
:::
---
## Placements
import Image from '@theme/IdealImage'
A **Placement** is a specific location within your app where ads are displayed. It is defined by the ad format, size, and position on the screen.
You can create multiple placements for different ad formats, such as banners, interstitials, and rewarded videos.
You can find your **Placement ID** on the **Source & Blocking Rules** page of the BidMachine dashboard. Copy this ID and include it in your SDK integration.
:::tip Placement Management API
You can also create, update, and delete placements programmatically via the [Placement Management API](/api/bidmachine-placement-management-api) — useful when provisioning placements at scale.
:::
1. Go to the **Source & Blocking Rules** page in the BidMachine dashboard.
2. Select correct **Source** from the list and choose edit.
3. Select the **Placements** tab.
4. Fill out the form to create a new placement:
- **Name**: A descriptive name for the placement.
- **Platform**: The platform for which the placement is created (e.g., Android, iOS).
- **Bundle**: The app bundle identifier where the placement will be used.
- **Ad Type**: The type of ad (e.g., Banner, Interstitial, Rewarded Video).
- **Placement Type**: The method of ad serving (e.g., Bidding – real-time auction; Waterfall – sequential requests by priority).
- **HVA Setup**: A parallel setup with a higher price floor to capture high-value impressions (e.g., parallel config with higher price floor; low fill, higher revenue).
- **Price Floor**: Minimum CPM required to serve an ad (e.g., requests below this value are skipped in the waterfall).
:::important Bundle Format
Android bundle name should be in the format `com.example.appname`, while iOS bundle should be numeric store ID (e.g., `123456789`).
:::
5. Click **Create** to save the placement.
6. The newly created placement will appear in the list of placements for the selected source.
7. Copy the **Placement ID** from the list and include it in your SDK integration by clicking on the **Copy** button next to the ID.
:::important Placement ID Usage
The Placement ID is used to identify the specific placement in your app.
It should be included in the ad request to ensure that the correct ads are served.
:::
---
## Source
import Image from '@theme/IdealImage'
A **Source** is a container you integrate into your app to display ads to users. The BidMachine platform automatically recognizes the ad type when the ad request is generated.
You can find your **Source ID** on the **Source & Blocking Rules** page of the BidMachine dashboard. Copy this ID and include it in your SDK integration.
---
## Enumerated Lists Specification
## Ad Position
| Value | Description |
| ----- | --------------------------------------------------------------------------------------- |
| `0` | Unknown |
| `1` | Above the Fold |
| `2` | *Deprecated* May or may not be initially visible depending on screen size/resolution. |
| `3` | Below the Fold |
| `4` | Header |
| `5` | Footer |
| `6` | Sidebar |
| `7` | Full Screen |
## API Frameworks
| Value | Description |
| ----- | ------------ |
| `1` | VPAID 1.0 |
| `2` | VPAID 2.0 |
| `3` | MRAID-1 |
| `4` | ORMMA |
| `5` | MRAID-2 |
## Banner Ad Types
| Value | Description |
| ----- | -------------------------------------------------- |
| `1` | XHTML Text Ad (usually mobile) |
| `2` | XHTML Banner Ad (usually mobile) |
| `3` | JavaScript Ad; must be valid XHTML (script tags) |
| `4` | `iframe` |
## Connection Type
| Value | Description |
| ----- | ------------------------------------- |
| `0` | Unknown |
| `1` | Ethernet |
| `2` | Wi‑Fi |
| `3` | Cellular Network – Unknown Generation |
| `4` | Cellular Network – 2G |
| `5` | Cellular Network – 3G |
| `6` | Cellular Network – 4G |
## Content Categories
:::warning
List is truncated; see full IAB taxonomy as needed.
:::
| Value | Description |
| -------- | ---------------------------- |
| `IAB1` | Arts & Entertainment |
| `IAB1-1` | Books & Literature |
| `IAB1-2` | Celebrity Fan/Gossip |
| `IAB1-3` | Fine Art |
| `IAB1-4` | Humor |
| `IAB1-5` | Movies |
| `IAB1-6` | Music |
| `IAB1-7` | Television |
| `IAB2` | Automotive |
| `IAB2-1` | Auto Parts |
| `IAB2-2` | Auto Repair |
| `IAB2-3` | Buying/Selling Cars |
| `IAB2-4` | Car Culture |
| ... | ... |
## Content Delivery Methods
| Value | Description |
| ----- | ------------- |
| `1` | Streaming |
| `2` | Progressive |
## Creative Attributes
| Value | Description |
| ----- | ---------------------------------------------------------- |
| `1` | Audio Ad (Auto-Play) |
| `2` | Audio Ad (User Initiated) |
| `3` | Expandable (Automatic) |
| `4` | Expandable (User Initiated—Click) |
| `5` | Expandable (User Initiated—Rollover) |
| `6` | In-Banner Video Ad (Auto-Play) |
| `7` | In-Banner Video Ad (User Initiated) |
| `8` | Pop (Over, Under, or Upon Exit) |
| `9` | Provocative or Suggestive Imagery |
| `10` | Shaky/Flashing/Flickering/Extreme Animation/Smileys |
| `11` | Surveys |
| `12` | Text Only |
| `13` | User Interactive (e.g., Embedded Games) |
| `14` | Windows Dialog or Alert Style |
| `15` | Has Audio On/Off Button |
| `16` | Ad Can Be Skipped (e.g., Skip Button on Pre-Roll Video) |
## Device Type
| Value | Description |
| ----- | ------------------- |
| `1` | Mobile/Tablet |
| `2` | Personal Computer |
| `3` | Connected TV |
| `4` | Phone |
| `5` | Tablet |
| `6` | Connected Device |
| `7` | Set Top Box |
## Expandable Direction
| Value | Description |
| ----- | ------------- |
| `1` | Left |
| `2` | Right |
| `3` | Up |
| `4` | Down |
| `5` | Full Screen |
## Location Type
| Value | Description |
| ----- | ------------------------------------ |
| `1` | GPS/Location Services |
| `2` | IP Address |
| `3` | User Provided (e.g., registration) |
## No-Bid Reason Codes
| Value | Description |
| ----- | ------------------------------ |
| `0` | Unknown Error |
| `1` | Technical Error |
| `2` | Invalid Request |
| `3` | Known Web Spider |
| `4` | Suspected Non-Human Traffic |
| `5` | Cloud/Data Center/Proxy IP |
| `6` | Unsupported Device |
| `7` | Blocked Publisher or Site |
| `8` | Unmatched User |
## Loss Reason Codes
| Value | Description |
| ----- | ------------------------------------------------------------------------------------------ |
| `0` | Bid Won |
| `1` | Internal Error |
| `2` | Impression Opportunity Expired |
| `3` | Invalid Bid Response |
| `4` | Invalid Deal ID |
| `5` | Invalid Auction ID |
| `6` | Invalid (malformed) Advertiser Domain |
| `7` | Missing Markup |
| `8` | Missing Creative ID |
| `9` | Missing Bid Price |
| `10` | Missing Minimum Creative Approval Data |
| `100` | Bid was Below Auction Floor |
| `101` | Bid was Below Deal Floor |
| `102` | Lost to Higher Bid |
| `103` | Lost to a Bid for a PMP Deal |
| `104` | Buyer Seat Blocked |
| `200` | Creative Filtered—General; reason unknown. |
| `201` | Creative Filtered—Pending processing by Exchange (e.g., approval, transcoding) |
| `202` | Creative Filtered—Disapproved by Exchange |
| `203` | Creative Filtered—Size Not Allowed |
| `204` | Creative Filtered—Incorrect Creative Format |
| `205` | Creative Filtered—Advertiser Exclusions |
| `206` | Creative Filtered—App Bundle Exclusions |
| `207` | Creative Filtered—Not Secure |
| `208` | Creative Filtered—Language Exclusions |
| `209` | Creative Filtered—Category Exclusions |
| `210` | Creative Filtered—Creative Attribute Exclusions |
| `211` | Creative Filtered—Ad Type Exclusions |
| `212` | Creative Filtered—Animation Too Long |
| `213` | Creative Filtered—Not Allowed in PMP Deal |
| `503` | Bid Expiration Below Minimum—bid.exp below 600s |
## VAST Companion Types
| Value | Description |
| ----- | -------------------|
| `1` | Static Resource |
| `2` | HTML Resource |
| `3` | `iframe` Resource |
## Video Bid Response Protocols
| Value | Description |
| ------ | --------------------- |
| `1` | VAST 1.0 |
| `2` | VAST 2.0 |
| `3` | VAST 3.0 |
| `4` | VAST 1.0 Wrapper |
| `5` | VAST 2.0 Wrapper |
| `6` | VAST 3.0 Wrapper |
## Video Linearity
| Value | Description |
| ----- | ------------------ |
| `1` | Linear / In-Stream |
| `2` | Non-Linear / Overlay|
## Video Playback Methods
| Value | Description |
| ----- | --------------------- |
| `1` | Auto-Play Sound On |
| `2` | Auto-Play Sound Off |
| `3` | Click-to-Play |
| `4` | Mouse-Over |
## Video Quality
| Value | Description |
| ----- | ----------------------------- |
| `0` | Unknown |
| `1` | Professionally Produced |
| `2` | Prosumer |
| `3` | User Generated (UGC) |
## Video Start Delay
| Value | Description |
| ------- | ----------------------------------------------- |
| `>0` | Mid-Roll (value indicates start delay in seconds)|
| `0` | Pre-Roll |
| `-1` | Generic Mid-Roll |
| `-2` | Generic Post-Roll |
---
## Bid Request Examples
:::note
BidMachine exchange currently works with Open RTB **2.3** and **2.5**.
Provided examples are only valid for Open RTB **2.5.**
:::
## Banner Bid Request
Banner Bid Request Example
```json title="Banner Bid Request"
{
"allimps": 0,
"app":
{
"bundle": "ru.kuchaknig.android.freebooks.scifi",
"cat":
[
"IAB1-1"
],
"ext":
{
"badv":
[],
"bcat":
[],
"packagename": "ru.kuchaknig.android.freebooks.scifi"
},
"id": "16848",
"name": "Фантастика",
"paid": 0,
"publisher":
{
"id": "618",
"name": "Роман"
},
"storeurl": "https://play.google.com/store/apps/details?id=ru.kuchaknig.android.freebooks.scifi&hl=en",
"ver": "2.9.37"
},
"at": 2,
"badv":
[],
"bcat":
[],
"cur":
[
"USD"
],
"device":
{
"carrier": "250-01",
"connectiontype": 3,
"devicetype": 4,
"geo":
{
"country": "RUS",
"lat": 56.8519,
"lon": 60.6122,
"type": 2,
"utcoffset": 300,
"zip": "620002"
},
"h": 1280,
"hwv": "DOOGEE HT16",
"ifa": "6d670e54-ffe3-4318-9100-dd600ee040c4",
"ip": "213.87.249.67",
"js": 1,
"language": "ru",
"lmt": 0,
"make": "DOOGEE",
"model": "DOOGEE HT16",
"os": "android",
"osv": "6.0",
"ua": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19(KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
"w": 720
},
"id": "d5260eec-75d9-4f7d-86bc-22b01b4c779e",
"imp":
[
{
"banner":
{
"api":
[
5,
3
],
"battr":
[
5,
8,
9,
10,
14
],
"h": 50,
"mimes":
[
"image/jpg",
"image/gif",
"image/png"
],
"w": 320
},
"bidfloor": 0.945,
"bidfloorcur": "USD",
"displaymanager": "appodeal",
"displaymanagerver": "1.15.8",
"id": "e58013b7-3e6e-4bcf-9121-1bcedeeb319c",
"instl": 0,
"tagid": "1"
}
],
"source":
{
"ext":
{
"schain":
{
"complete": 1,
"nodes":
[
{
"asi": "seller.com",
"hp": 1,
"rid": "7578222740099842730",
"sid": "210676"
},
{
"asi": "bidmachine.io",
"hp": 1,
"rid": "ce4d7ece-aa68-4e9b-91f5-fc581ed0bde4",
"sid": "124"
}
],
"ver": "1.0"
}
},
"fd": 1,
"tid": "7578222740099842730"
},
"tmax": 500,
"user":
{
"gender": "F",
"geo":
{
"country": "RUS",
"lat": 56.8519,
"lon": 60.6122,
"type": 2,
"utcoffset": 300,
"zip": "620002"
}
}
}
```
## Interstitial Bid Request
:::info
If Exchange is requesting a **rewarded (non-skippable)** interstitial, then we **ALWAYS** send `"battr": [16]` in Banner object. We also send `imp.banner.ext.bannertype: "rewarded"` inside bid request.
If Exchange is requesting a **skippable interstitial**, then we **DO NOT** send `"battr": [16]` in Banner object.
:::
Interstitial Bid Request Example
```json title="Interstitial Bid Request"
{
"app":
{
"bundle": "1214661054",
"cat":
[
"IAB1-6",
"IAB14"
],
"ext":
{
"badv":
{},
"bcat":
{},
"packagename": "com.boom.topaudio"
},
"id": "68629",
"name": "Top Audio",
"publisher":
{
"id": "1582",
"name": "Роман"
},
"storeurl": "https://itunes.apple.com/de/app/top-audio-excellent-player/id1214661054?mt=8&uo=4",
"ver": "1.1"
},
"at": 2,
"cur":
[
"USD"
],
"device":
{
"carrier": "250-02",
"connectiontype": 2,
"devicetype": 4,
"geo":
{
"city": "Troitsa",
"country": "RUS",
"ext":
{
"old_geo":
{
"country": "RUS",
"lat": 55.4792,
"lon": 37.3086,
"type": 2,
"utcoffset": 180,
"zip": "142190"
}
},
"ipservice": 3,
"lat": 55.4792,
"lon": 37.3086,
"type": 2,
"utcoffset": 180,
"zip": "142190"
},
"h": 568,
"hwv": "iPhone6,2",
"ifa": "10133A31-C4BF-489E-A310-B9241861E439",
"ip": "212.41.49.81",
"js": 1,
"language": "ru",
"make": "Apple",
"model": "iPhone6,2",
"os": "ios",
"osv": "10.1.1",
"ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Mobile/14B100",
"w": 320
},
"id": "12f71145-a0f0-4b8b-a513-c051d0bb4159",
"imp":
[
{
"banner":
{
"api":
[
5,
3
],
"battr":
[
14,
5,
8,
9,
10
],
"h": 480,
"mimes":
[
"image/jpg",
"image/gif",
"image/png"
],
"w": 320
},
"bidfloor": 13.568,
"bidfloorcur": "USD",
"displaymanager": "appodeal",
"displaymanagerver": "1.3.9",
"id": "e9761ecc-f2fb-47b0-99d4-bc1a67cab07d",
"instl": 1,
"tagid": "3"
}
],
"source":
{
"ext":
{
"schain":
{
"complete": 1,
"nodes":
[
{
"asi": "fyber.com",
"hp": 1,
"rid": "7578222740099842730",
"sid": "210676"
},
{
"asi": "bidmachine.io",
"hp": 1,
"rid": "ce4d7ece-aa68-4e9b-91f5-fc581ed0bde4",
"sid": "124"
}
],
"ver": "1.0"
}
},
"fd": 1,
"tid": "7578222740099842730"
},
"tmax": 500,
"user":
{
"gender": "O",
"geo":
{
"country": "RUS",
"lat": 55.4792,
"lon": 37.3086,
"type": 2,
"utcoffset": 180,
"zip": "142190"
}
}
}
```
## Rewarded Interstitial Bid Request
:::info
For nonskippalbe (rewarded interstitials) we add `"imp.banner.ext.bannertype: "rewarded"` to bid request
:::
Rewarded Bid Request Example
```json title="Rewarded Bid Request"
{
"app":
{
"bundle": "1214661054",
"cat":
[
"IAB1-6",
"IAB14"
],
"ext":
{
"badv":
{},
"bcat":
{},
"packagename": "com.boom.topaudio"
},
"id": "68629",
"name": "Top Audio",
"publisher":
{
"id": "1582",
"name": "Роман"
},
"storeurl": "https://itunes.apple.com/de/app/top-audio-excellent-player/id1214661054?mt=8&uo=4",
"ver": "1.1"
},
"at": 2,
"cur":
[
"USD"
],
"device":
{
"carrier": "250-02",
"connectiontype": 2,
"devicetype": 4,
"geo":
{
"city": "Troitsa",
"country": "RUS",
"ext":
{
"old_geo":
{
"country": "RUS",
"lat": 55.4792,
"lon": 37.3086,
"type": 2,
"utcoffset": 180,
"zip": "142190"
}
},
"ipservice": 3,
"lat": 55.4792,
"lon": 37.3086,
"type": 2,
"utcoffset": 180,
"zip": "142190"
},
"h": 568,
"hwv": "iPhone6,2",
"ifa": "10133A31-C4BF-489E-A310-B9241861E439",
"ip": "212.41.49.81",
"js": 1,
"language": "ru",
"make": "Apple",
"model": "iPhone6,2",
"os": "ios",
"osv": "10.1.1",
"ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Mobile/14B100",
"w": 320
},
"id": "12f71145-a0f0-4b8b-a513-c051d0bb4159",
"imp":
[
{
"banner":
{
"api":
[
5,
3
],
"battr":
[
14,
5,
8,
9,
10
],
"ext":
{
"bannertype": "rewarded"
},
"h": 480,
"mimes":
[
"image/jpg",
"image/gif",
"image/png"
],
"w": 320
},
"bidfloor": 13.568,
"bidfloorcur": "USD",
"displaymanager": "appodeal",
"displaymanagerver": "1.3.9",
"id": "e9761ecc-f2fb-47b0-99d4-bc1a67cab07d",
"instl": 1,
"tagid": "3"
}
],
"source":
{
"ext":
{
"schain":
{
"complete": 1,
"nodes":
[
{
"asi": "fyber.com",
"hp": 1,
"rid": "7578222740099842730",
"sid": "210676"
},
{
"asi": "bidmachine.io",
"hp": 1,
"rid": "ce4d7ece-aa68-4e9b-91f5-fc581ed0bde4",
"sid": "124"
}
],
"ver": "1.0"
}
},
"fd": 1,
"tid": "7578222740099842730"
},
"tmax": 500,
"user":
{
"gender": "O",
"geo":
{
"country": "RUS",
"lat": 55.4792,
"lon": 37.3086,
"type": 2,
"utcoffset": 180,
"zip": "142190"
}
}
}
```
## Video Bid Request
Video Bid Request Example
```json title="Video Bid Request"
{
"allimps": 0,
"app":
{
"cat":
[
"IAB24"
],
"ext":
{
"app_uptime": 1317,
"badv":
{},
"bcat":
[
"IAB-30"
],
"click":
{},
"click_count": 0,
"finish":
{},
"finish_count": 4,
"imp":
{},
"imp_count": 4,
"packagename": "com.appodeal.sandbox",
"sdk": "2.1.10",
"session_id": 13,
"session_uptime": 15,
"tclick":
{},
"tfinish":
{
"interstitial": 4
},
"timp":
{
"interstitial": 4
}
},
"id": "7635",
"name": "Appodeal Sandbox",
"privacypolicy": 0,
"publisher":
{
"id": "1819",
"name": "pub name"
},
"storeurl": "This app is not in store yet",
"ver": "4.0"
},
"at": 2,
"badv":
[],
"bcat":
[
"IAB-30"
],
"cur":
[
"USD"
],
"device":
{
"connectiontype": 2,
"devicetype": 4,
"ext":
{
"battery": -100,
"rooted": "false"
},
"geo":
{
"city": "Kirov",
"country": "RUS",
"lat": 58.5969,
"lon": 49.6583,
"type": 2,
"utcoffset": 180,
"zip": "610000"
},
"h": 320,
"hwv": "x86_64",
"ifa": "CCBD556A-14A7-4E26-A52C-652355D4BA5A",
"ip": "77.72.140.9",
"js": 1,
"lmt": 0,
"make": "Apple",
"model": "x86_64",
"os": "iOS",
"osv": "11.2",
"ppi": 326,
"pxratio": 2,
"ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_2 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Mobile/15C107",
"w": 568
},
"id": "ca0463e4-0c19-42c4-99e9-534713c6ee84",
"imp":
[
{
"bidfloor": 10.01,
"bidfloorcur": "USD",
"displaymanager": "appodeal",
"displaymanagerver": "2.1.10",
"id": "c1816ba0-d005-4d19-a11e-49147712e5b1",
"instl": 1,
"tagid": "82",
"video":
{
"api":
[],
"battr":
[
16
],
"delivery":
[
1,
2
],
"ext":
{
"videotype": "rewarded"
},
"h": 320,
"linearity": 1,
"maxduration": 30,
"mimes":
[
"video/mp4"
],
"minduration": 5,
"playbackmethod":
[
1
],
"protocols":
[
1,
2,
3,
4,
5,
6
],
"w": 480
}
}
],
"regs":
{
"coppa": 0
},
"tmax": 300,
"user":
{
"gender": "O",
"geo":
{
"city": "Kirov",
"country": "RUS",
"lat": 58.5969,
"lon": 49.6583,
"type": 2,
"utcoffset": 180,
"zip": "610000"
}
}
}
```
## Native Ad Bid Request
Native Ad Bid Request Example
```json title="Native Ad Bid Request"
{
"allimps": 0,
"app":
{
"bundle": "1134511982",
"cat":
[
"IAB9-30",
"IAB9-30"
],
"ext":
{
"badv":
[],
"bcat":
[],
"packagename": "com.tigrido.color6"
},
"id": "41944",
"name": "Color 6 (iOS)",
"paid": 0,
"privacypolicy": 0,
"publisher":
{
"id": "2089",
"name": "Aleksandr Filatov"
},
"storeurl": "https://itunes.apple.com/us/app/color-6/id1134511982?mt=8&uo=4",
"ver": "1.0"
},
"at": 2,
"badv":
[],
"bcat":
[],
"cur":
[
"USD"
],
"device":
{
"connectiontype": 2,
"devicetype": 4,
"geo":
{
"city": "Kirov",
"country": "RUS",
"lat": 58.5966,
"lon": 49.6601,
"type": 2,
"utcoffset": 180,
"zip": "249440"
},
"h": 568,
"hwv": "x86_64",
"ifa": "9611032A-935B-472A-878E-D4CBD9D4B192",
"ip": "77.72.140.9",
"js": 1,
"language": "en",
"lmt": 0,
"make": "Apple",
"model": "x86_64",
"os": "iOS",
"osv": "10.3.1",
"ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E8301",
"w": 320
},
"id": "d97cef2b-36be-44fe-90ed-15f90666bbe7",
"imp":
[
{
"bidfloor": 0.0858,
"bidfloorcur": "USD",
"displaymanager": "appodeal",
"displaymanagerver": "1.3.9",
"id": "ae7c1c88-de6a-4893-8474-fe491024d159",
"instl": 0,
"native":
{
"api":
[
1,
2,
3,
4,
5
],
"request": "{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"len\":40}},{\"id\":124,\"required\":1,\"img\":{\"type\":1,\"wmin\":50,\"hmin\":50,\"mimes\": [\"image/jpg\",\"image/gif\",\"image/png\",\"image/jpeg\"]}},{\"id\":128,\"required\":1,\"img\":{\"type\":3,\"wmin\":1200,\"hmin\":627,\"mimes\":[\"image/jpg\",\"image/gif\",\"image/png\",\"image/jpeg\"]}},{\"id\":4,\"required\":0,\"video\":{\"mimes\":[\"video/mp4\"],\"minduration\":1,\"maxduration\":90,\"protocols\":[2,5]}},{\"id\":127,\"required\":1,\"data\":{\"type\":2}},{\"id\":7,\"required\":0,\"data\":{\"type\":3}},{\"id\":8,\"required\":0,\"data\":{\"type\":12}}],\"ver\":\"1.0\",\"plcmtcnt\":1,\"seq\":0}",
"ver": "1.1"
},
"tagid": "34"
}
],
"regs":
{
"coppa": 0
},
"tmax": 250,
"user":
{
"gender": "O",
"geo":
{
"city": "Kirov",
"country": "RUS",
"lat": 58.5966,
"lon": 49.6601,
"type": 2,
"utcoffset": 180,
"zip": "249440"
}
}
}
```
---
## MRAID Ads Requirements
## Impression Tracking with MRAID Creative
To track impressions inside the creative, include a script that triggers impression trackers on the `viewableChange` event:
```js
```
:::warning
If you are using impression pixels in the creative, move them to `seatbid.bid.ext.imptrackers` (the Bid object) or trigger them within the `viewableChange` event.
:::
---
## Bid Request Specification
:::note
BidMachine Ad Exchange currently works with Open RTB **2.3** and **2.5**.
This documentation is only valid for Open RTB **2.5.**
Outgoing bid requests are sent with the `x-openrtb-version: 2.5` HTTP header.
:::
## Bid Request Object
| Attribute | Type | Description | Example |
|---|---|---|---|
| `id` | string | Unique ID of the bid request, provided by the exchange. | `d5260eec-75d9-4f7d-86bc-22b01b4c779e` |
| `imp` | object array | Array of Imp objects representing the impressions offered. At least 1 Imp object is required. | *(empty)* |
| `app` | object | Details about the publisher’s app (i.e., non-browser applications). Only applicable and recommended for apps. | *(empty)* |
| `device` | object | Details about the user’s device to which the impression will be delivered. | *(empty)* |
| `user` | object | Details about the human user of the device; the advertising audience. | *(empty)* |
| `test` | integer; default 0 | Indicator of test mode in which auctions are not billable, where 0 = live mode, 1 = test mode | `0` |
| `at` | integer; default 1 | Auction type, where 1 = First Price, 2 = Second Price Plus. BidMachine currently supports only type 1 | `1` |
| `tmax` | integer | Maximum time in milliseconds to submit a bid to avoid timeout. This value is commonly communicated offline. | `250` |
| `cur` | string array | Array of allowed currencies for bids on this bid request using ISO-4217 alpha codes. Recommended only if the exchange accepts multiple currencies. | `["USD"]` |
| `bcat` | string array | Blocked advertiser categories using the IAB content categories. | `["IAB2-1"]` |
| `badv` | string array | Block list of advertisers by their domains. | `["blocked.domain.com"]` |
| `reg` | object | A Regs object that specifies any industry, legal, or governmental regulations in force for this request. | *(empty)* |
| `source` | object | This object describes the nature and behavior of the entity that is the source of the bid request upstream from the exchange. | *(empty)* |
| `ext` | object | Placeholder for exchange-specific extensions to OpenRTB | *(empty)* |
## Imp
| Attribute | Type | Description | Example |
|---|---|---|---|
| `id` | **required**,string | A unique identifier for this impression within the context of the bid request (typically, starts with 1 and increments OR UUID). | `6ba06f9a-44c8-497d-8bc3-78804bebc2c8` |
| `banner` | object | A Banner object; required if this impression is offered as a banner ad opportunity. | *(empty)* |
| `video` | object | A Video object; required if this impression is offered as a video ad opportunity. | *(empty)* |
| `native` | object | A Native object; required if this impression is offered as a native ad opportunity. | *(empty)* |
| `displaymanager` | required,string | Name of ad mediation partner, SDK technology, or player responsible for rendering ad (typically video or mobile). Used by some ad servers to customise ad code by a partner. Recommended for video and/or apps. | `you_ssp_name` |
| `displaymanagerver` | required,string | Version of ad mediation partner, SDK technology, or player responsible for rendering ad (typically video or mobile). Used by some ad servers to customise ad code by a partner. Recommended for video and/or apps. | `2.0.0` |
| `instl` | optional,integer; default 0 | `1` = interstitial/fullscreen, `0` = not interstitial. | `0` |
| `tagid` | optional,string | Identifier for specific ad placement or ad tag that was used to initiate the auction. Useful for debugging or optimization. | `my__debug__tag` |
| `bidfloor` | **required**,float; default 0 | Minimum bid for this impression expressed in CPM. | `0.15` |
| `bidfloorcur` | optional,string; default `"USD"` | Currency (ISO-4217 alpha code). May differ from bid response currency if allowed by exchange. | `USD` |
| `secure` | integer | Flag to indicate if the impression requires secure HTTPS URL creative assets and markup, where 0 = non-secure, 1 = secure. If omitted, the secure state is unknown, but non-secure HTTP support can be assumed. | 0 |
| `ext` | object | Placeholder for exchange-specific extensions to OpenRTB | *(empty)* |
## Banner Object
| Attribute | Type | Description | Example |
|---|---|---|---|
| `w` | integer | Width of the impression in pixels. If neither `wmin` nor `wmax` are specified, this value is an exact width requirement. Otherwise it is a preferred width. | `320` |
| `h` | integer | Height of the impression in pixels. If neither `hmin` nor `hmax` are specified, this value is an exact height requirement. Otherwise it is a preferred height. | `50` |
| `wmax` | integer | Maximum width of the impression in pixels. If included along with a `w` value then `w` should be interpreted as a recommended or preferred width. | `320` |
| `hmax` | integer | Maximum height of the impression in pixels. If included along with an `h` value then `h` should be interpreted as a recommended or preferred height. | `50` |
| `wmin` | integer | Minimum width of the impression in pixels. If included along with a `w` value then `w` should be interpreted as a recommended or preferred width. | `320` |
| `hmin` | integer | Minimum height of the impression in pixels. If included along with an `h` value then `h` should be interpreted as a recommended or preferred height. | `50` |
| `id` | string | Unique identifier for this banner object. Recommended when Banner objects are used with a Video object to represent an array of companion ads. Values usually start at 1 and increase with each object; should be unique within an impression. | `ap1gm-0jioruind-1ffopjgo1p` |
| `btype` | integer array | Blocked banner ad types. | `[2]` |
| `battr` | integer array | Blocked creative attributes. BidMachine currently blocks: "Expandable (User Initiated - Rollover)", "Pop (e.g., Over, Under, or Upon Exit)", "Provocative or Suggestive Imagery", "Shaky, Flashing, Flickering, Extreme Animation, Smileys", "Windows Dialog or Alert Style" | `[5,8,9,10,14]` |
| `pos` | integer | Ad position on screen. | `5` |
| `mimes` | string array | Content MIME types supported. BidMachine supports: `"image/png"`, `"text/javascript"`, `"text/html"`, `"image/jpg"`, `"image/gif"`. | `["image/jpg","image/gif","image/png"]` |
| `topframe` | integer | Indicates if the banner is in the top frame as opposed to an iframe, where `0` = no, `1` = yes. | `1` |
| `api` | integer array | List of supported API frameworks for this impression. If not explicitly listed, it is assumed not to be supported. | `[5,3]` |
| `ext` | object | Placeholder for exchange-specific extensions to OpenRTB. | `{"bannertype":"rewarded"}` |
## Native
| Attribute | Type | Description | Example |
|---|---|---|---|
| `request` | string | Request payload complying with the Native Ad Specification. | `"89oghjnr"` |
| `ver` | string | Version of the Native Ad Specification to which request complies; highly recommended for efficient parsing. | `"1.0"` |
| `api` | integer array | List of supported API frameworks for this impression. If not explicitly listed, assumed unsupported. | `[1]` |
| `battr` | integer array | Blocked creative attributes. | `[5,3]` |
## Video
| Attribute | Type | Description | Example |
|---|---|---|---|
| `mimes` | string array | Content MIME types supported. | `["video/mp4"]` |
| `minduration` | integer | Minimum video ad duration in seconds. | `5` |
| `maxduration` | integer | Maximum video ad duration in seconds. | `30` |
| `protocol` | integer | Supported video bid response protocol. Use of `protocols` is recommended. At least one must be specified in either. | `[1]` |
| `protocols` | integer array | Array of supported video bid response protocols. | `[1,2,6]` |
| `w` | integer | Width of the video player in pixels. | `320` |
| `h` | integer | Height of the video player in pixels. | `480` |
| `startdelay` | integer | Indicates the start delay in seconds for pre-roll, mid-roll, or post-roll ad placements. | `1` |
| `linearity` | integer | Indicates if the impression must be linear, nonlinear, etc. If none specified, assume all are allowed. | `1` |
| `battr` | integer array | Blocked creative attributes. **IMPORTANT:** if you need rewarded video — send `[16]` here. | `[1,3]` |
| `minbitrate` | integer | Minimum bit rate in Kbps. Exchange may set this dynamically or universally across publishers. | `128` |
| `maxbitrate` | integer | Maximum bit rate in Kbps. Exchange may set this dynamically or universally across publishers. | `512` |
| `playbackmethod` | integer array | Allowed playback methods. If none specified, assume all are allowed. | `[1,2,3,4]` |
| `delivery` | integer array | Supported delivery methods (e.g., streaming, progressive). If none specified, assume all are supported. | `[1,2]` |
| `pos` | integer | Ad position on screen. | `[3]` |
| `companiodad` | object array | Array of banner objects if companion ads are available. | *(empty)* |
| `api` | integer array | Supported API frameworks. If not listed, assumed unsupported. | `[1,2,3,4,5]` |
| `companiontype` | integer array | Supported VAST companion ad types. Recommended if companion Banner objects are included. | `[1]` |
| `ext` | object | Placeholder for exchange-specific extensions to OpenRTB. | `{"videotype": "rewarded"}` |
| `ext.orientation` | optional | Forwarded verbatim from `imp.video.ext` of the upstream supply source. Not always present. BidMachine does not generate, validate, or interpret this value; DSPs must not rely on it being present or on any particular value set. | — |
## App Object
| Attribute | Type | Description | Example |
|---|---|---|---|
| `id` | string | Exchange-specific app ID. | `"102938"` |
| `name` | string | App name (may be aliased at the publisher’s request). | `"TestApp"` |
| `bundle` | string | Application bundle or package name (e.g., com.app.game); intended to be a unique ID across exchanges. iOS will pass the app store ID, android – the package bundle. | android: `"com.app.test"`iOS: `"78945611"` |
| `domain` | string | Domain of the app. | `"game.app.com"` |
| `storeurl` | string | App store URL for an installed app; for QAG 1.5 compliance. | `https://itunes.apple.com/us/app/somerandomapp/id1191231238?mt=8` |
| `cat` | string array | Array of IAB content categories of the app. | `["IAB2-1", "IAB2-4"]` |
| `sectioncat` | string array | Array of IAB content categories that describe the current section of the app. | `["IAB2"]` |
| `pagecat` | string array | Array of IAB content categories that describe the current page or view of the app. | `["IAB2-1"]` |
| `ver` | string | Application version. | `"1.0.3"` |
| `privacypolicy` | integer | Indicates if the app has a privacy policy, where 0 = no, 1 = yes. | `1` |
| `paid` | integer | 0 = app is free, 1 = the app is a paid version. | `1` |
| `publisher` | object | Details about the Publisher of the app. | *(empty)* |
| `keywords` | string | Comma separated list of keywords about the app. | `"automotive"` |
| `ext` | object | Placeholder for exchange-specific extensions to OpenRTB. BidMachine sends sdk version, time of the session, session id, app uptime, number of impressions and clicks. | `{ "sdk": "2.0.0", "session_uptime": 36, "session_id": 56, "app_uptime": 31995, "impressions_count": 142, "clicks_count": 27 }` |
## Device Object
| Attribute | Type | Description | Example |
|---------------|---------------|----------------------------------------------------------------------------------------------------------|---------|
| `ua` | string | Browser user agent string. | `"Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X) AppleWebKit/602.3.12 (KHTML, like Gecko) Mobile/14C89"` |
| `geo` | object | Location of the device assumed to be the user’s current location defined by a Geo object. | *(empty)* |
| `dnt` | integer | "Do Not Track" flag: 0 = unrestricted, 1 = do not track. | `0` |
| `lmt` | integer | "Limit Ad Tracking" flag: 0 = unrestricted, 1 = limited per commercial guidelines. | `1` |
| `ip` | string | IPv4 address closest to device. | `"23.227.207.23"` |
| `ipv6` | string | IPv6 address closest to device. | *(empty)* |
| `devicetype` | integer | The general type of device. | `4` |
| `make` | string | Device make. | `"Apple"` |
| `model` | string | Device model. | `"iPhone"` |
| `os` | string | Device operating system. | `"iOS"` |
| `osv` | string | Device operating system version. | `"10.1.3"` |
| `hmw` | string | Hardware version of the device. | `"5S"` |
| `h` | integer | Physical height of the screen in pixels. | `568` |
| `w` | integer | Physical width of the screen in pixels. | `320` |
| `ppi` | integer | Screen size in pixels per linear inch. | `326` |
| `pxratio` | float | Ratio of physical pixels to device-independent pixels. | `2` |
| `js` | integer | Support for JavaScript: 0 = no, 1 = yes. | `1` |
| `language` | string | Browser language using ISO-639-1-alpha-2. | `"en"` |
| `carrier` | string | Carrier or ISP (e.g., "VERIZON"). "WIFI" is used to indicate high bandwidth. | *(empty)* |
| `connectiontype` | integer | Network connection type. | `2` |
| `ifa` | string | ID sanctioned for advertiser use in the clear (i.e., not hashed). | `382A78A3-7EA0-4D3B-9724-0231C07D0C5A` |
| `didsha1` | string | Hardware device ID (e.g., IMEI), hashed via SHA1. | `9db9123123b7fe382df2efeeb0176d2216cff7e` |
| `didmd5` | string | Hardware device ID (e.g., IMEI), hashed via MD5. | `12f2f79bb5b7fe382df2efeeb0176da2216cff7e` |
| `dpidsha1` | string | Platform device ID (e.g., Android ID), hashed via SHA1. | `a12f1479bb5b7fe382df2efeeb0176d16cff7e` |
| `dpidmd5` | string | Platform device ID (e.g., Android ID), hashed via MD5. | `12sff9bb5b7fe382df2efeeb0176d2216cff7e` |
| `macsha1` | string | MAC address of the device, hashed via SHA1. | `12sff9bb5b7fe382df2efeeb0176d2216cff7e` |
| `macmd5` | string | MAC address of the device, hashed via MD5. | `12sff9bb5b7fe382df2efeeb0176d2216cff7e` |
| `ext` | object | Placeholder for exchange-specific extensions. BidMachine sends info about battery state and rooted flag. | `{"battery": -100, "rooted": "false"}` |
## User Object
| Attribute | Type | Description | Example |
|---|---|---|---|
| `id` | string | Exchange-specific ID for the user. At least one of `id` or `buyerid` is recommended. | `"1"` |
| `buyerid` | string | Buyer-specific ID for the user as mapped by the exchange for the buyer. At least one of `buyerid` or `id` is recommended. | `"1"` |
| `yob` | integer | Year of birth as a 4-digit integer. | `1984` |
| `gender` | string | Gender, where `"M"` = male, `"F"` = female, `"O"` = other. *(Omitted means unknown)* | `"O"` |
| `keywords` | string | Comma-separated list of keywords, interests, or intent. | `"game"` |
| `geo` | object | Location of the user’s home base defined by a Geo object. This is not necessarily their current location. | *(empty)* |
| `data` | object array | Additional user data. Each Data object represents a different data source. | *(empty)* |
| `ext` | object array | Placeholder for exchange-specific extensions to OpenRTB. | `{"consent" : "1"}` |
## Data Object
| Attribute | Type | Description | Example |
|---|---|---|---|
| `id` | string | Exchange-specific ID for the data provider. | `"2"` |
| `name` | string | Exchange-specific name for the data provider. | `"test"` |
| `segment` | object array | Array of Segment objects that contain the actual data values. | *(empty)* |
## Segment Object
| Attribute | Type | Description | Example |
|---|---|---|---|
| `id` | string | ID of the data segment specific to the data provider. | `"12"` |
| `name` | string | Name of the data segment specific to the data provider. | `"address"` |
| `value` | string | String representation of the data segment value. | `"Delaware, Wilmington, 19809, United States"` |
## Geo Object
| Attribute | Type | Description | Example |
|-------------|---------|-------------|---------|
| `lat` | float | Latitude from -90.0 to +90.0, where negative is south. | `15` |
| `lon` | float | Longitude from -180.0 to +180.0, where negative is west. | `30` |
| `type` | integer | Source of location data; recommended when passing lat/lon. | `2` |
| `country` | string | Country code using ISO-3166-1-alpha-3 | `"USA"` |
| `region` | string | Region code using ISO-3166-2; 2-letter state code if USA. | `"US"` |
| `city` | string | City using United Nations Code for Trade & Transport Locations. See Appendix A for a link to the codes. | `"New York"` |
| `zip` | string | Zip or postal code. | `"19809"` |
| `utcoffset` | integer | Local time as the number +/- of minutes from UTC. | `180` |
## Publisher Object
| Attribute | Type | Description | Example |
|---|---|---|---|
| `id` | string | Exchange-specific publisher ID. | `"12"` |
| `name` | string | Publisher name (may be aliased at the publisher’s request). | `"test_name"` |
| `cat` | string array | Array of IAB content categories that describe the publisher. | `["IAB2-1"]` |
| `domain` | string | Highest level domain of the publisher. | `"publisher.com"` |
## GDPR
| Parameter | Type | Values | Example Values |
|---|---|---|---|
| `regs.ext.gdpr` | integer | `0`: GDPR does not apply to this traffic `1`: GDPR applies to this traffic | `0` |
| `user.ext.consent` | string | Consent string per [IAB TCF spec](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/a32574941ce201708e30e78702278efe1ce6cd59/Consent%20string%20and%20vendor%20list%20formats%20v1.1%20Final.md). Also supports:`"0"`: consent NOT given`"1"`: consent given | `"BOJObISOJObISAABAAENAA4AAAAAoAAA"` |
## Regs
| Attribute | Type | Description | Example |
|---|---|---|---|
| `coppa` | integer | Flag indicating if this request is subject to COPPA regulations (USA FTC), where `0` = no, `1` = yes. | `1` |
| `ext` | object | Extension for GDPR information. | `{ "gdpr": 0 }` |
## Source Object
| Attribute | Type | Description | Example |
|---|---|---|---|
| `fd` | int | Entity responsible for the final impression sale decision, where `0` = exchange, `1` = upstream source. | `1` |
| `tid` | string | Transaction ID that must be common across all participants in this bid request (e.g., potentially multiple exchanges). | `6ba06f9a-44c8-497d` |
| `pchain` | optional,string | Payment ID chain string containing embedded syntax described in the TAG Payment ID Protocol v1.0. Pass-through field: sent only when the upstream supply source provides it, so DSPs must not rely on it being present. | `7tury102i-7uf7` |
| `ext` | object | Placeholder for exchange-specific extensions to OpenRTB. | *(empty)* |
## Source Ext Object
:::info
`ext` object is used to provide schain info. It goes under source.ext.schain path
:::
| Attribute | Type | Description | Example |
|---|---|---|---|
| `ext.schain` | object | This object represents both the links in the supply chain as well as an indicator whether or not the supply chain is complete. | *(empty)* |
## Schain Object Properties
:::info
For more information please refer to official [IAB documentation](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md)
:::
| Attribute | Type | Description | Example |
|---|---|---|---|
| `complete` | integer | Flag indicating whether the chain contains all nodes involved in the transaction leading back to the owner of the site, app or other medium of the inventory, where `0` = no, `1` = yes. | `1` |
| `nodes` | object array | Array of SupplyChainNode objects in the order of the chain. In a complete supply chain, the first node represents the initial advertising system and seller ID involved in the transaction. In an incomplete supply chain, it represents the first known node. The last node represents the entity sending this bid request. | *(empty)* |
| `ver` | string | Version of the supply chain specification in use, in the format of `"major.minor"` (e.g., `"1.0"`). | `"1.0"` |
| `ext` | object | Placeholder for advertising-system specific extensions to this object. | *(empty)* |
## Nodes Object Properties
| Attribute | Type | Description |
|---|---|---|
| `asi` | string | The canonical domain name of the SSP, Exchange, Header Wrapper, etc., that bidders connect to. This may differ from the parent corporate domain to support WHOIS and reverse IP lookups. Should match the value used in `ads.txt` if available. |
| `sid` | string | Identifier for the seller/reseller account within the advertising system. Typically maps to `publisher.id` in OpenRTB or the publisher’s org ID in OpenDirect. Max length: 64 characters. |
| `rid` | string | The `request.id` as issued by this seller. |
| `name` | string | Legal company name paid for inventory. Should be omitted if listed in `sellers.json`. *(optional)* |
| `domain` | string | Business domain of the represented entity. Should be omitted if listed in `sellers.json`. *(optional)* |
| `hp` | integer | Indicates if this node is involved in payment flow. `1` = involved, `0` = not involved. Required in version 1.0; future versions may support non-payment nodes. |
| `ext` | object | Placeholder for system-specific extensions. |
## User Contextual Data
:::note
User Level Contextual Data is defined by the SDK but can be overwritten by an App/Mediation via the SDK API
:::
| Name | Type | Description | Example |
|------|------|-------------|---------|
| `request.context.user.ext.impdepth` | uint32 | The count of impressions for a specific placement type in a given app session. **Deprecated in 3.0.0** | `5` |
| `request.context.user.ext.sessionduration` | uint64 | The total duration of time a user has spent so far in a specific app session expressed in seconds. | `55` |
| `request.context.user.ext.lastbundle` | string | The last app bundle the user saw on the previous impression in a given session per placement type. **Deprecated in 3.0.0** | `"bundle"` |
| `request.context.user.ext.lastadomain` | string | The last advertiser domain the user saw on the previous impression in a given session per placement type. **Deprecated in 3.0.0** | `"domain"` |
| `request.context.user.ext.clickrate` | float | The percentage of clicks/impressions per user per placement type over a given number of impressions, where 5 represents a 5% CTR. Applies only to Rewarded and Video. **Deprecated in 3.0.0** | `5` |
| `request.context.user.ext.lastclick` | bool | Indicates if the user clicked on the last impression, where `1` = clicked, `0` = didn’t click. **Deprecated in 3.0.0** | `1` |
| `request.context.user.ext.completionrate` | float | Percentage of completions/impressions per user for a given number of impressions, where 70 represents 70% completion. **Deprecated in 3.0.0** | `70` |
## Device Contextual Data
| Name | Type | Description | Example |
|------|------|-------------|---------|
| `request.context.device.ext.inputlanguage` | list[string] | List of user languages. | `["DE", "US"]` |
| `request.context.device.ext.diskspace` | double | Value of available free disk space. | `61347.0` |
| `request.context.device.ext.totaldisk` | double | Value of total disk space. | `112221.0` |
| `request.context.device.ext.ringmute` | bool | Device sound setting at ad request time. | `1 - yes`, `0 - no` |
| `request.context.device.ext.charging` | bool | Is the device charging. | `1 - yes`, `0 - no` |
| `request.context.device.ext.batterylevel` | float | Battery level. `1` - full charge, `0.1` - 10%, `0` - empty. | — |
| `request.context.device.ext.batterysaver` | bool | Battery saver enabled. | `1 - yes`, `0 - no` |
| `request.context.device.ext.darkmode` | bool | Dark mode enabled. | `1 - yes`, `0 - no` |
| `request.context.device.ext.airplane` | bool | (Android only) Airplane mode enabled. | `1 - yes`, `0 - no` |
| `request.context.device.ext.dnd` | bool | (Android only) "Do Not Disturb" setting enabled. | `1 - yes`, `0 - no` |
| `request.context.device.ext.devicename` | string | User-defined name of the device. | `iPhone 14 Pro` |
| `request.context.device.ext.time` | uint64 | POSIX timestamp, depends on device settings. | `1680197719.5890589` |
| `request.context.device.ext.headset` | bool | Is a wired headset connected. | `1 - yes`, `0 - no` |
| `request.context.device.ext.headsetname` | string | Identifier of connected wireless headset. | `"Headset"` |
| `request.context.device.ext.screenbright` | double | Brightness level of screen from 0.0 to 1.0. | `0...1` |
| `request.context.device.ext.jailbreak` | bool | Is the device jailbroken. | `1 - yes`, `0 - no` |
| `request.context.device.ext.lastbootup` | uint64 | Android: ms since boot incl. sleep. iOS: POSIX timestamp of last boot. | `1676623341.589673` |
| `request.context.device.ext.totalmem` | uint64 | Total RAM in bytes. | `34359738368 B` |
| `request.context.device.ext.atts` | int | App tracking authorization status: `0` - Not Determined, `1` - Restricted, `2` - Denied, `3` - Authorized. Sent on any OS when supplied by the SDK or supply source. | — |
## App Contextual Data
| Name | Type | Description | Example |
|------|------|-------------|---------|
| `request.context.app.ext.install_time` | uint64 | Unix timestamp in milliseconds of the application install (might be zero). **Available since SDK 3.0.1** | `0.0` |
| `request.context.app.ext.first_launch_time` | uint64 | Unix timestamp in milliseconds of the first BidMachine SDK launch. **Available since SDK 3.0.1 and data can be incorrect for devices updated from older app/sdk version** | `1.725296223359E12` |
| `request.context.app.ext.min_api_level` | uint32 | (Android only) Minimal supported Android SDK version. | `21` |
| `request.context.app.ext.kotlin_version` | string | Kotlin runtime version. | `1.8.20` |
---
## Bid Response Examples
## Banner Bid Response
Banner Bid Response Example
```json title="Banner Bid Response"
{
"cur": "USD",
"id": "eb85349d-03c3-44f4-a77b-824f7221d116",
"seatbid":
[
{
"bid":
[
{
"adid": "1378ygfvn928ouyghf19oiuhg03r",
"adm": "",
"adomain":
[
"adomain.com"
],
"cid": "iy4wuygh7i3rukgh91ol",
"crid": "iy4wuygh7i3rukgh91ol_123124",
"ext":
{
"imptrackers":
[
"https://tracker1.com/ad?price=${AUCTION_PRICE}&cur=${AUCTION_CURRENCY}",
"https://tracker1.com/ad?avid=[ADVERTISER_ID]&pricePaid=[PRICE_PAID]&priceBid=[BID_PRICE]"
]
},
"id": "1fwdsg1gdsgwfdb",
"impid": "23fsdfsdg-12312fds-44f4-12dfsfa-824f7221d116",
"nurl": "http://example.com/win/1378ygfvn928ouyghf19oiuhg03r?won=${AUCTION_PRICE}&impid={AUCTION_IMP_ID}&auction=${AUCTION_ID}&bidid=${AUCTON_BID_ID}",
"price": 1.1200
}
],
"seat": "772"
}
]
}
```
## Interstitial Bid Response
### HTML Interstitial Example
HTML Interstitial Bid Response Example
```json title="Interstitial Bid Response"
{
"cur": "USD",
"id": "eb85349d-03c3-44f4-a77b-824f7221d116",
"seatbid":
[
{
"bid":
[
{
"adid": "121rf13gdsf12gdsg",
"adm": "",
"adomain":
[
"adomain.com"
],
"cid": "iy4wuygh7i3rukgh91ol",
"crid": "iy4wuygh7i3rukgh91ol_123124",
"ext":
{
"imptrackers":
[
"https://tracker1.com/ad?price=${AUCTION_PRICE}&cur=${AUCTION_CURRENCY}",
"https://tracker1.com/ad?avid=[ADVERTISER_ID]&pricePaid=[PRICE_PAID]&priceBid=[BID_PRICE]"
]
},
"id": "1fwdsg1gdsgwfdb",
"impid": "23fsdfsdg-12312fds-44f4-12dfsfa-824f7221d116",
"nurl": "http://example.com/win/121rf13gdsf12gdsg?won=${AUCTION_PRICE}&impid={AUCTION_IMP_ID}&auction=${AUCTION_ID}&bidid=${AUCTON_BID_ID}",
"price": 1.1200
}
],
"seat": "772"
}
]
}
```
### MRAID Interstitial Example
MRAID Interstitial Bid Response Example
```json title="Interstitial Bid Response"
{
"ext":
{
"impTrackers":
[
"http://imp.url/?type=IMPRESSION&bidRequestId=${AUCTION_ID}&winPrice=${AUCTION_PRICE}"
]
},
"id": "324ca3eb-295d-4da4-8956-d7945572f068",
"seatbid":
[
{
"bid":
[
{
"adm": " ",
"adomain":
[
"9nl.org"
],
"cid": "campaign123-ads216-campaign",
"crid": "5081233",
"id": "324ca3eb-295d-4da4-8956-d7945572f068:1",
"impid": "1",
"nurl": "http://bit.ly/2u4sBuo?bidRequestId=${AUCTION_ID}&winPrice=${AUCTION_PRICE}",
"price": 1.613
}
],
"seat": "0"
}
]
}
```
### MRAID Playable Interstitial Example
MRAID Playable Interstitial Bid Response Example
```json title="MRAID Playable Bid Response"
{
"cur": "USD",
"id": "5cfeb1d3-0498-4ba0-8806-db66a861dd34",
"seatbid":
[
{
"bid":
[
{
"adid": "85593_27327",
"adm": "Connecting to Game Server...",
"adomain":
[
"adomain.com"
],
"attr":
[
13
],
"cat":
[
"IAB9-30"
],
"cid": "cid_123",
"crid": "crid_123",
"ext":
{
"crtype": "MRAID playable"
},
"id": "beeaf85a-c022-4678-80be-0e500f4643d7_171110-14__206",
"impid": "f3832082-ae9b-456a-b5f6-0792db707d50",
"iurl": "http://image.url/image.jpg",
"nurl": "https://node206.fractionalmedia.com/win2_notice_bin?bid_id=beeaf85a-c022-4678-80be-0e500f4643d7_171110-14__206&cid=85593&settlement=${AUCTION_PRICE}",
"price": 30.0
}
]
}
]
}
```
## Video Bid Response
### Simple VAST Bid Response Example
VAST Bid Response Example
```json title="VAST Bid Response"
{
"bidid": "6df766aa-367a-4b9b-8054-3cf3ed116868",
"cur": "USD",
"id": "7d3ad9c0_5289e2a8-45a9-4a3c-b71f-144186d6ce05",
"seatbid":
[
{
"bid":
[
{
"adid": "24857",
"adm": "\n \n \n Exebid.DCA\n \n \n \n \n \n \n 00:00:28\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n",
"adomain":
[
"microsoft.com"
],
"attr":
[
16
],
"cat":
[
"IAB9-30"
],
"cid": "4146",
"crid": "24857",
"crtype": "VAST 2.0",
"h": 360,
"id": "BB876A0B-E9AB-4E49-109A-AF38D0909379",
"impid": "1",
"nurl": "https://example.bid/win?ic_id=6df766aa-367a-4b9b-8054-3cf3ed116868&return=vast&win_price=${AUCTION_PRICE}&exchange_noise=",
"price": 1.3895836807293,
"w": 640
}
],
"seat": "140"
}
]
}
```
### VAST with MRAID Playable Companion Bid Response Example
VAST with MRAID Playable Companion Bid Response Example
```json title="VAST Bid Response"
{
"id": "29e8574f-1add-423a-a083-e47c5623841f",
"seatbid":
[
{
"bid":
[
{
"adid": "255",
"adm": "2.000:00:22 ]]> http://google.com",
"adomain":
[
"www.adomain.com"
],
"attr":
[
6
],
"cat":
[
"IAB1-4",
"IAB1-5"
],
"cid": "campaign178-ads263",
"crid": "banner1",
"h": 360,
"id": "29e8574f-1add-423a-a083-e47c5623841f:1",
"impid": "1",
"iurl": "https://i.url/image.jpg",
"nurl": "http://wintracking.url:8766/?bidRequestId=${AUCTION_ID}&winPrice=${AUCTION_PRICE}",
"price": 1.833,
"w": 480
}
],
"seat": "0"
}
]
}
```
## Native Ad Bid Response
Native Ad Bid Response Example
```json title="Native Ad Bid Response"
{
"bidid": "3992480bfea3c39d6395ff8f3e8815418d4caac5c69152f457f4884d",
"cur": "USD",
"id": "9ebb0958-2262-4089-97e0-0c64ca47c6da1475643469279",
"seatbid":
[
{
"bid":
[
{
"adm": "{\"native\":{\"assets\":[{\"id\":123,\"title\":{\"text\":\"Appreciate\"}},{\"id\":124,\"img\":{\"h\":80,\"url\":\"http://z.tpbid.com/ssb/1/images/31ff0db2743c3d3150a002173c99d67f.png\",\"w\":80}},{\"id\":128,\"img\":{\"h\":627,\"url\":\"http://z.tpbid.com/ssb/1/images/abf50143ac85610407a17f72be03e388.jpg\",\"w\":1200}},{\"data\":{\"value\":\"Discover great apps!\"},\"id\":127},{\"data\":{\"value\":\"4.5\"},\"id\":7},{\"data\":{\"value\":\"INSTALL\"},\"id\":8}],\"imptrackers\":[\"http://appodeal.herokuapp.com/imp/native/abb0dea1?bid_id=3992480bfea3c39d6395ff8f3e8815418d4caac5c69152f457f4884d&price=${AUCTION_PRICE}&eaid=${AUCTION_ID}&as=1&exp_uuid=8b02940ac60ee55c1936eef123ffbc24\"],\"link\":{\"url\":\"http://test.tpbid.com/click?bid_id=3992480bfea3c39d6395ff8f3e8815418d4caac5c69152f457f4884d&ep0=yB1&ep1=VxdPKlaf&cf=1&redirect_to=https%3a%2f%2fplay.google.com%2fstore%2fapps%2fdetails%3fid%3dcom.triapodi.apprec%26bid_id%3dus-3992480bfea3c39d6395ff8f3e8815418d4caac5c69152f457f4884d\"}}}",
"adomain":
[
"triapodi.com"
],
"bundle": "com.triapodi.apprec",
"cid": "1_f7e7c50d874690515cebae47f2d6fb2c",
"crid": "1_75deab27575de8b261aedc57fd02caf4",
"h": 0,
"id": "1",
"impid": "1",
"iurl": "http://z.tpbid.com/ssb/1/images/abf50143ac85610407a17f72be03e388.jpg",
"nurl": "http://appodeal.herokuapp.com/nurl",
"price": 10.882,
"w": 0
}
]
}
]
}
```
---
## Macroses
:::note
BidMachine Exchange currently works with OpenRTB 2.5.
:::
| Macro | Description |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| ``${AUCTION_ID}`` | ID of the bid request (from `BidRequest.id`). |
| ``${AUCTION_BID_ID}`` | ID of the bid (from `BidResponse.id`). |
| ``${AUCTION_IMP_ID}`` | ID of the impression won (from `imp.id`). |
| ``${AUCTION_SEAT_ID}`` | ID of the bidder seat. |
| ``${AUCTION_AD_ID}`` | ID of the ad markup to serve (from `bid.adid`). |
| ``${AUCTION_PRICE}`` | Settlement price (same currency and units as the bid). |
| ``${AUCTION_CURRENCY}`` | Currency of the bid; for confirmation purposes. |
| ``${AUCTION_MBR}`` | Market Bid Ratio (clearance price ÷ bid price). |
| ``${AUCTION_LOSS}`` | Loss reason code (see Loss Reason Codes). |
| ``${AUCTION_MINIMUM_BID_TO_WIN}``, ``${AUCTION_MIN_TO_WIN}`` | Minimum bid required to win the auction. |
---
## Bid Response Specification
| Attribute | Type | Description | Example |
|---|---|---|---|
| `id` | string; required | ID of the bid request to which this is a response. | `"eb85349d-03c3-44f4-a77b-824f7221d116"` |
| `seatbid` | object array | Array of seatbid objects; 1+ required if a bid is to be made. | *(empty)* |
| `bidid` | string | Bidder generated response ID to assist with logging/tracking. | `"1asd24ht3hg0-fk1pmfflkdmsfk-12flkfdfd"` |
| `cur` | string; default "USD" | Bid currency using ISO-4217 alpha codes. | `"USD"` |
| `nbr` | integer | Reason for not bidding. | `1` |
## Seatbid Object
| Attribute | Type | Description | Example |
|---|---|---|---|
| `bid` | object array; required | Array of 1+ Bid objects each related to an impression. Multiple bids can relate to the same impression. | *(empty)* |
| `seat` | string | ID of the bidder seat on whose behalf this bid is made. | `"123"` |
| `group` | integer; default 0 | `0` = impressions can be won individually; `1` = impressions must be won or lost as a group. | `0` |
## Bid Object
| Attribute | Type | Description | Example |
|---|---|---|---|
| `id` | string; required | Bidder generated bid ID to assist with logging/tracking. | `"1fwdsg1gdsgwfdb"` |
| `impid` | string; required | ID of the Imp object in the related bid request. | `"23fsdfsdg-12312fds-44f4-12dfsfa-824f7221d116"` |
| `price` | float; required | Bid price expressed as CPM. Integer math is recommended for currencies. | `1.15` |
| `adid` | string | ID of a preloaded ad to be served if the bid wins. | `"1378ygfvn928ouyghf19oiuhg03r"` |
| `nurl` | string | Win notice URL called if the bid wins. | `http://example.com/win/...?won=${AUCTION_PRICE}` |
| `lurl` | string | Loss notice URL called when a bid is lost. | `http://example.com/loss/...?final_price=${AUCTION_PRICE}` |
| `adm` | string | Ad markup in case of win (supersedes nurl if both present). | `"AD"` |
| `adomain` | string array; required | Advertiser domains (for blocklist checking). | `["test-domain.com"]` |
| `bundle` | string | App bundle being advertised. | `android: "com.test.app", iOS: "8120398"` |
| `iurl` | string | Image URL for ad quality/safety checking. | `http://example.com/i/...` |
| `cid` | string | Campaign ID. | `"12341"` |
| `crid` | string | Creative ID. | `"231"` |
| `cat` | string array | IAB content categories of the creative. | `["IAB3-1"]` |
| `attr` | integer array | Creative attributes. | `[1,2,13]` |
| `h` | integer | Height of the creative in pixels. | `480` |
| `w` | integer | Width of the creative in pixels. | `320` |
| `ext` | object; optional | Bidder-specific extensions. `ext.imptrackers` is a BidMachine extension carrying impression tracking URLs. | `{"imptrackers": ["https://..."]}` |
| `burl` | string; optional | Standard OpenRTB billing notice URL, called by the exchange when the impression occurs. | `http://example.com/bill_imp/...` |
:::note
`bid.burl` and `bid.ext.imptrackers` are interchangeable: the exchange reads and processes both, neither is required, and a DSP may send either one or both. Using only one of them does not break tracking.
See [nURL and Impression Tracking Schemes](/dsp/other/nurl-and-impression-tracking-schemes) for the exact firing order per ad type.
:::
:::note
BidMachine does not expect and does not accept any rendering-experience confirmation field in the bid response. There is no field for a DSP to report which video experience (`placement`, `plcmt`, or `linearity`) was actually rendered.
`crtype` is populated by BidMachine itself on the supply-facing side of the exchange and is derived from the placement type. It is not a DSP-facing bid response field: DSPs do not populate it, and the exchange does not read it from a bid response.
:::
---
## CTR Templates
import './ctr-templates.css';
import Image from '@theme/IdealImage';
export const Arrow = () => (
);
export const Stage = ({src, title, sub}) => (
{title}{sub}
);
Over the past few years, BidMachine has introduced new ad templates and rendering improvements to enhance the user experience and increase engagement. These changes have a direct impact on how users interact with ads and on the resulting CTR levels.
We recognize that transparency is essential in the relationship between BidMachine and DSPs. For that reason, we provide partners with a **clear view of how ads are presented** to users, along with a programmatic way to **control the experience**.
Ad experiences
Every template that can be served, from the most conservative to the highest-engagement flows.
Measured CTR ranges
Ranges observed across billions of impressions, so you know what to expect for each template.
Programmatic controls
The bid-response signal that lets you adjust the experience to your campaign objectives.
## Fullscreen video ad format {#fullscreen-video}
Five templates form a ladder from the most conservative rendering to the highest-engagement, multi-stage flow. Each is selected with the `campaign_type` signal in the bid response.
01
Low CTR template
The most conservative template from a CTR perspective.
CTR rangeBelow 5%
Bid response signal
campaign_type: low_ctr
UI details
Only video is displayed
Close time: 0s Ad is immediately skippable
Close button size: big
Fullscreen clickability disabled Interacting with the video pauses or resumes it
Only the small “learn more” button is clickable
02
Baseline template
Keeps the ad experience as close as possible to the original creative.
CTR range5–15%depending on creative
Bid response signal
campaign_type: baseline_ctr
UI details
Only video is displayed
Close time: 5s
Close button size: medium
Fullscreen clickability disabled Interacting with the video pauses or resumes it
Only the small “learn more” button is clickable
03
Mid CTR template
Introduces a multi-stage experience by supporting the end card.
CTR range15–25%depending on creative
Bid response signal
campaign_type: mid_ctr
UI details
Both video and end card (when available) are displayed
Close time: 5s
Close button size: medium
Fullscreen clickability enabled Interacting with the video initiates the click rather than pausing/resuming
“Learn more” button not displayed
Experience flow
04
High CTR template
Enriches the flow with two new touchpoints: a 2nd end card and a custom CTA.
CTR range25–35%depending on creative
Bid response signal
campaign_type: high_ctr
Requires bid.bundle presence.
UI details
Both video and end card are displayed
Close time: 10s
Close button size: small
Fullscreen clickability enabled Interacting with the video initiates the click rather than pausing/resuming
“Learn more” button not displayed
A 2nd end card is generated and added as a 3rd stage Video + 1st end card + 2nd end card
A persistent CTA is generated and displayed above the video
Experience flow
05
Highest CTR template
Mainly enables the skip-to-store feature — ideal for app-install campaigns.
CTR rangeAbove 60%
Bid response signal
campaign_type: highest_ctr
Requires bid.bundle presence.
UI details
Both video and end card are displayed
Close time: 10s
Close button size: small
Fullscreen clickability enabled Interacting with the video initiates the click rather than pausing/resuming
“Learn more” button not displayed
A 2nd end card is generated and added as a 3rd stage Video + 1st end card + 2nd end card
A persistent CTA is generated and displayed above the creative
Skip-to-store feature enabled
It uses native components such as SKProductView (SKPV) on iOS, so the user is not redirected outside the host app and can download the advertised bundle without any friction.
Experience flow
## Rewarded fullscreen video ad format {#rewarded-video}
For the rewarded fullscreen video ad format, we follow the same configuration described above.
The only difference is the overall duration of the ad experience: always 30s before becoming closeable. CTR is on average higher than for non-rewarded video, but still falls within the ranges above.
## Fullscreen HTML / MRAID ad types {#mraid}
For HTML / MRAID creatives, the templates differ mainly in close timing, close-button size, and the close-to-store behavior.
01
Low CTR templateThe most conservative template from a CTR perspective.
CTR rangeBelow 5%depending on creative
Bid response signalcampaign_type: low_ctr
UI detailsClose time: 0sClose button size: big
02
Mid CTR templateChanges the close time and the close-button size.
CTR range5–10%depending on creative
Bid response signalcampaign_type: mid_ctr
UI detailsClose time: 5sClose button size: medium
03
High CTR templateChanges the close time and the close-button size.
CTR range10–20%depending on creative
Bid response signalcampaign_type: high_ctr
UI detailsClose time: 10sClose button size: small
04
Highest CTR templateAdds the close-to-store feature.
CTR rangeAbove 70%
Bid response signalcampaign_type: highest_ctr
UI detailsClose time: 10sClose button size: smallClose-to-store enabled User is redirected to the landing page when the ad is closed
## Fullscreen rewarded HTML / MRAID ad types {#rewarded-mraid}
The rewarded HTML / MRAID variants extend the close time to satisfy the reward requirement while keeping the same close-button progression.
01
Low CTR templateThe most conservative template from a CTR perspective.
CTR rangeBelow 7%depending on creative
Bid response signalcampaign_type: low_ctr
UI detailsClose time: 30sClose button size: big
02
Mid CTR templateChanges the close time and the close-button size.
CTR range7–13%depending on creative
Bid response signalcampaign_type: mid_ctr
UI detailsClose time: 30sClose button size: medium
03
High CTR templateChanges the close time and the close-button size.
CTR range14–20%depending on creative
Bid response signalcampaign_type: high_ctr
UI detailsClose time: 30sClose button size: small
04
Highest CTR templateAdds the close-to-store feature.
CTR rangeAbove 70%
Bid response signalcampaign_type: highest_ctr
UI detailsClose time: 30sClose button size: smallClose-to-store User is redirected to the landing page when the ad is closed
## Bid response sample {#bid-response-sample}
The template is selected through the `campaign_type` field inside `seatbid.bid.ext` of the bid response.
```json title="bid-response.json" {10}
{
"id": "...",
"seatbid": [
{
...
"bid": [
{
...
"ext": {
"campaign_type": "highest_ctr"
}
}
]
}
],
...
}
```
---
## Deep Linking
Deep linking is a powerful technique that enhances user engagement and improves campaign performance. It allows advertisers to direct users straight to specific pages or content within an app.
## How Deep Linking Works
### Installed App
If a user has already installed the advertised app, the deep link URL will seamlessly navigate them to the desired in-app destination — such as:
- A product page
- A specific level in a game
- A relevant content section
### App Not Installed
If the user doesn't have the app installed, the deep link will utilize a **fallback mechanism** to guide them to the next best action defined by the advertiser — such as:
- Redirecting to the App Store / Google Play Store
- Opening an optimized mobile landing page
## Identifying Eligible Supply
Impressions that support deep linking are flagged directly on `imp.ext`:
```json
"imp": [
{
"ext": {
"deeplink": 1,
"fallback": 1
}
}
]
```
| Field | Type | Description |
|------------|---------|-------------------------------------------------------------------------------------|
| `deeplink` | integer | `1` — the impression supports opening a deep link on click |
| `fallback` | integer | `1` — the impression supports a fallback destination when the target app is missing |
Both fields are always sent together with the value `1`. They are never sent as `0` — their **absence** means the impression is not deep-link eligible.
An impression is flagged when both of the following are true:
- it carries a `banner` (including MRAID) or `video` object — native-only impressions are not flagged;
- the request comes from BidMachine SDK **3.2.0 or newer**.
The flag applies to **all** delivery options described below.
:::note
These fields sit at the top level of `imp.ext`, alongside `skadn`, `gpid` and other impression extensions — they are not nested inside a `deeplink` object.
:::
## Delivery Options
### 1. Plain deep link URL
Pass the deep link directly in the creative's click-through — the VAST `ClickThrough` and `CompanionClickThrough` elements for video, or the standard click URL for display / MRAID creatives.
No allowlisting, registration or other additional steps are required. Both of the following are supported:
- **Custom URI schemes** — for example `temu://`, `shein://`, `shopee://`, `aliexpress://`, `creditkarma://`, `walmart://`, `tiktok://`, and any other application scheme.
- **HTTP(S)-based deep links** — services such as AppsFlyer OneLink, URLGenius and comparable providers.
Use one of the options below instead if you need explicit control over the fallback destination or over primary / fallback tracking.
### 2. `deeplinker://` scheme
Encode the deep link fields as query parameters of a `deeplinker://navigate` URL, and place that URL in the VAST `ClickThrough` and, if an end card is included, the `CompanionClickThrough` elements. Display / MRAID creatives use the same URL as their click-through.
```text
deeplinker://navigate?
primaryUrl=customapp%3A%2F%2Flink&
primaryTrackingUrl=http%3A%2F%2Fpx.url.com%2FtrackPrimaryClicked&
fallbackUrl=http%3A%2F%2Fwww.url.com&
fallbackTrackingUrl=http%3A%2F%2Fpx.url.com%2FtrackFallbackClicked
```
:::warning Format
The protocol (`deeplinker://`) and host path (`navigate`) are mandatory, and all parameter values must be URL-encoded.
:::
### 3. `bid.ext` fields
Pass the deep link as discrete fields on the bid extension, instead of encoding them into a URL:
```json
"bid": [
{
"ext": {
"deeplink": "customapp://link",
"primary_tracking": "http://px.url.com/trackPrimaryClicked",
"fallback": "http://www.url.com",
"fallback_tracking": "http://px.url.com/trackFallbackClicked"
}
}
]
```
| Field | Required | Description |
|---------------------|----------|--------------------------------------------------------------------------------|
| `deeplink` | yes | Deep link to another application potentially installed on the user device |
| `primary_tracking` | no | Upon successful opening of the deep link, a GET request is sent to this URL |
| `fallback` | no | Link to a webpage if the desired app is not installed on the device |
| `fallback_tracking` | no | Upon successful opening of the fallback URL, a GET request is sent to this URL |
`deeplink` is mandatory — if it is absent, the remaining three fields are ignored and no deep link is applied to the bid.
URLs in `bid.ext` are passed as-is and must **not** be URL-encoded.
:::warning Same names, different meaning
`deeplink` and `fallback` appear on both sides of the transaction with different types:
- on `imp.ext` (bid request) they are **integer flags** signalling eligibility;
- on `bid.ext` (bid response) they are **URL strings** carrying the destinations.
:::
## `deeplinker://` Query Parameters
Used by the `deeplinker://navigate` scheme described above:
| Parameter | Description |
|---------------------|-----------------------------------------------------------------------------|
| `primaryUrl` | Deep link to another application potentially installed on the user device |
| `primaryTrackingUrl`| Upon successful opening of the primary URL, a GET request is sent to this URL |
| `fallbackUrl` | Link to a webpage if the desired app is not installed on the device |
| `fallbackTrackingUrl`| Upon successful opening of the fallback URL, a GET request is sent to this URL |
:::
---
## iOS Specifics
import SKAdNetwork from "@site/src/components/mdx/skadnetwork";
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
## Introduction
Due to the IDFA changes Apple is implementing in iOS 14 and later, BidMachine is adding support for Apple's [SKAdNetwork](https://developer.apple.com/documentation/storekit/skadnetwork) attribution.
This integration enables our programmatic demand buyers to track installs and conversions on iOS 14+ when IDFA is unavailable.
In addition to SKAdNetwork, BidMachine will provide contextual advertising data to help partners enhance targeting and modeling.
Below is an overview of how the integration works at the app/publisher level and the data flow during the auction.
## SKStoreProductViewController
SKStoreProductViewController (SKPV) is the preferred method for handling click URLs within the BidMachine SDK. The SDK employs the following prioritized approach to process and present ad clicks:
1. **SKAdNetwork Parameter Handling**: When an ad response contains SKAdNetwork parameters, the SDK prioritizes these parameters to present SKPV, bypassing the click URL entirely.
2. **Click URL Processing**: In the absence of SKAdNetwork parameters, the SDK processes the click URL through the following steps:
- **App Store Link Detection**: The SDK analyzes the click URL's scheme (`itms://`) and host to determine if it references the App Store. If validated as an App Store link, the SDK extracts the app bundle identifier and presents it using SKPV.
- **HTTP/HTTPS Redirect Resolution**: For HTTP/HTTPS URLs, the SDK performs a silent GET request to resolve all redirects and identify the final destination.
- **Final Destination Validation**: The SDK applies the same App Store link detection logic to the resolved destination URL.
3. **Fallback Behavior**: If the final destination is not an App Store link, or if SKPV presentation fails for any reason, the SDK defaults to opening the URL in the device's default browser.
## SKAdNetwork
Here is a high-level overview of how SKAdNetwork works in the context of BidMachine:
```mermaid
sequenceDiagram
participant DSP
participant BidMachine
participant Publisher as Direct Publisher/SSP
%% Integration phase
opt Integration
DSP ->> BidMachine: SKAdNetworkIdentifier
BidMachine ->> Publisher: All SKAdNetworkIdentifiers
end
%% Auction phase
opt Auction
Publisher ->> BidMachine: Ad request
note left of Publisher: • SKAdNetwork request data• IDs• Contextual data
BidMachine ->> DSP: Bid request
note left of BidMachine: • SKAdNetwork request data• IDs• Contextual data
DSP -->> BidMachine: Bid response
note right of DSP: • SKAdNetwork response data• Bid response
BidMachine -->> Publisher: Ad response
note right of BidMachine: • SKAdNetwork response data• Ad response
end
```
### SKAdNetwork IDs
Partners who wish to use BidMachine's SKAdNetwork solution should share their SKAdNetwork ID with their account manager.
If you don't have an account manager, register with Apple [here](https://developer.apple.com/documentation/storekit/skadnetwork/registering_an_ad_network).
BidMachine will provide publishers with an integration guide listing all SKAdNetwork IDs to add to their `Info.plist`.
SKAdNetwork IDs in Info.plist format
### Bid Request
BidMachine adds the following fields to BidRequests on iOS 14+ versions, categorized below:
| Object | Attribute | Description | Type | Example |
| ---------------------------- | ----------- | ------------------------------------------------------------------------------------------- | --------- | --------------------------------------------------- |
| `imp.ext.skadn` | `version` | SKAdNetwork SDK version (`"2.0"` or higher). Deprecated in favor of `versions` since 2.1. | `string` | `"2.0"` |
| `imp.ext.skadn` | `versions` | Supported SKAdNetwork versions (array of strings). | `string[]`| `["2.0","2.1","2.2"]` |
| `imp.ext.skadn` | `sourceapp` | Publisher app ID in Apple App Store (matches `app.bundle`). | `string` | `"1232526187"` |
| `imp.ext.skadn` | `overlay` | Flag indicating SKOverlay support (`0` or `1`). | `integer` | `1` |
| `imp.ext.skadn` | `autostore` | Flag indicating AutoStore support (`0` or `1`). | `integer` | `1` |
| `imp.ext.skadn` | `skadnetids`| Subset of SKAdNetwork IDs (from `Info.plist`) relevant to the DSP. | `string[]`| `["87yhbnd3gg.skadnetwork", ...]` |
```json
{
"imp": [
{
"ext": {
"skadn": {
"version": "2.0",
"versions": ["2.0","2.1","2.2"],
"sourceapp": "880047117",
"overlay": 1,
"skadnetids": [
"cdkw7geqsh.skadnetwork",
"qyjfv329m4.skadnetwork"
]
}
}
}
]
}
```
### Bid Response
If the DSP receives `imp.ext.skadn` in the bid request, they must include `seatbid.bid.ext.skadn` in the bid response. This enables BidMachine to submit click data and signatures for attribution.
**Properties of `seatbid.bid.ext.skadn`:**
| Attribute | Description | Type | Example |
| -------------- | ---------------------------------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------ |
| `version` | SKAdNetwork SDK version (`"2.0"` or higher). | `string` | `"2.0"` |
| `network` | SKAdNetwork ID matching one in `skadnetids` from the request. | `string` | `"87yhbnd3gg.skadnetwork"` |
| `campaign` | Campaign ID (1–100), as a string. | `string` | `"1"` |
| `itunesitem` | Advertiser app ID (matches `bid.bundle`). | `string` | `"1232526187"` |
| `fidelities` | Array of fidelity objects (introduced in SKAdNetwork v2.2). | `object[]`| See example below |
| `nonce` | Unique identifier per ad response. Deprecated in favor of `fidelities[n].nonce` since 2.2. | `string` | `"a9ff03c2-d7ef-11ea-87d0-0242ac130003"` |
| `sourceapp` | Publisher app ID (matches request `sourceapp`). | `string` | `"123456789"` |
| `overlay` | Flag indicating SKOverlay display. | `integer` | `1` |
| `timestamp` | Unix time (ms) at signature time. Deprecated in favor of `fidelities[n].timestamp` since 2.2. | `string` | `"1596723499812"` |
| `signature` | SKAdNetwork signature. Deprecated in favor of `fidelities[n].signature` since 2.2. | `string` | `"MZHKJHKhKJH…"` |
**`seatbid.bid.ext.skadn.fidelities` object:**
| Attribute | Description | Type | Example |
| ------------ | ----------------------------------------------------- | --------- | ----------------------------------------------- |
| `fidelity` | Fidelity type of the attribution. | `integer` | `0` |
| `nonce` | Unique identifier per ad response. | `string` | `"473b1a16-b4ef-43ad-9591-fcf3aefa82a7"` |
| `timestamp` | Unix time (ms) at signature time. | `string` | `"1594406341232"` |
| `signature` | SKAdNetwork signature. | `string` | `"MEQCIEQlmZRNfYzK…"` |
```json
{
"seatbid": [
{"bid": [
{"ext": {"skadn": {
"version": "2.2",
"network": "cdkw7geqsh.skadnetwork",
"campaign": "45",
"itunesitem": "123456789",
"sourceapp": "880047117",
"overlay": 1,
"fidelities": [
{
"fidelity": 0,
"signature": "MEQCIEQlmZRNfYzK…",
"nonce": "473b1a16-b4ef-43ad-9591-fcf3aefa82a7",
"timestamp": "1594406341232"
}
]
}}}
]}
]
}
```
```json
{
"seatbid": [
{"bid": [
{"ext": {"skadn": {
"version": "2.2",
"network": "cdkw7geqsh.skadnetwork",
"campaign": "45",
"itunesitem": "123456789",
"sourceapp": "880047117",
"overlay": 1,
"fidelities": [
{
"fidelity": 0,
"signature": "MEQCIEQlmZRNfYzK…",
"nonce": "473b1a16-b4ef-43ad-9591-fcf3aefa82a7",
"timestamp": "1594406341232"
},
{
"fidelity": 1,
"signature": "GRlMDktMmE5Zi00Z…",
"nonce": "e650de09-2a9f-4dc3-a4d1-544c402e9095",
"timestamp": "1594406341233"
}
]
}}}
]}
]
}
```
```json
{
"seatbid": [
{"bid": [
{"ext": {"skadn": {
"version": "2.0",
"network": "cdkw7geqsh.skadnetwork",
"campaign": "45",
"itunesitem": "880047117",
"nonce": "473b1a16-b4ef-43ad-9591-fcf3aefa82a7",
"sourceapp": "123456789",
"overlay": 1,
"timestamp": "1594406341232",
"signature": "MEQCIEQlmZRNfYzKBSE8QnhLTIHZZZWCFgZpRqRxHss65KoFAiAJgJKjdrWdkLUOCCjuEx2RmFS7daRzSVZRVZ8RyMyUXg=="
}}}
]}
]
}
```
### Click Through & Click Tracking
When SKAdNetwork is enabled and a valid `skadn` object is in the bid response:
- **iOS SDK** opens a `SKStoreProductViewController` with the `skadn` values.
- VAST `ClickThrough`, `CompanionClickThrough`, `MRAID.open()`, and standard HTML `` links are processed in the background. HTTP redirects are followed; non-redirect responses are ignored.
- VAST `ClickTracking` and `CompanionClickTracking` continue to function as usual.
If no `skadn` object is found, the SDK falls back to normal click-through behavior.
## AdAttributionKit
BidMachine supports Apple's [AdAttributionKit](https://developer.apple.com/documentation/adattributionkit) framework for iOS 17.4+
and BidMachine SDK 3.1.0 to help DSPs and advertisers track ad performance and conversions.
Here is a high-level overview of how Apple adattributionKit works in the context of BidMachine:
```mermaid
sequenceDiagram
participant DSP
participant BidMachine
participant Publisher as Direct Publisher/SSP
%% Integration phase
opt Integration
DSP ->> BidMachine: AdNetworkIdentifier
BidMachine ->> Publisher: All AdNetworkIdentifiers
end
%% Auction phase
opt Auction
Publisher ->> BidMachine: Ad request
note left of Publisher: • AdAttributionKit request data• IDs• Contextual data
BidMachine ->> DSP: Bid request
note left of BidMachine: • AdAttributionKit request data• IDs• Contextual data
DSP -->> BidMachine: Bid response
note right of DSP: • AdAttributionKit response data• Bid response
BidMachine -->> Publisher: Ad response
note right of BidMachine: • AdAttributionKit response data• Ad response
end
```
---
## nURL and Impression Tracking Schemes
We support two schemes for tracking impressions and triggering `nURL`.
Below you can find two block schemes for different ad types:
- [Banner & Interstitial Ad Scheme](#banner--interstitial-scheme)
- [Video Ad Scheme](#video-ad-scheme)
:::danger Important
`bURL` is tracked at the time server gets an impression, irrespective of the tracking scheme.
:::
## Banner & Interstitial Scheme
```mermaid
sequenceDiagram
participant App
participant SDK as BidMachine SDK Renderer
participant Exchange as BidMachine Exchange Server
participant DSP1 as DSP-1
participant DSP2 as DSP-2
participant T1 as https://tracker1.com
participant T2 as https://tracker2.com
%% 1. Ad Request & Auction
App->>Exchange: Ad Request
Exchange->>DSP1: Bid Request
Exchange->>DSP2: Bid Request
note over DSP1,DSP2: Auction
alt DSP-1 wins
Exchange->>DSP1: Winner notification • adm (markup) • ext.imptrackers = ["https://tracker1.com", "https://tracker2.com"] • nURL (win-notify) • bURL (billing)
DSP1-->>Exchange: Bid Response
else DSP-2 wins
Exchange->>DSP2: Winner notification • adm (markup) • ext.imptrackers = ["https://tracker1.com", "https://tracker2.com"] • nURL (delayed-notify) • bURL (billing)
DSP2-->>Exchange: Bid Response
end
Exchange-->>App: Bid Response
%% 2. Notification schemes
note right of Exchange: Server-side nURL win notification: • nURL pinged immediately by server • bURL held until impression
note right of App: Client-side delayed notification: • ext.imptrackers[] in body • nURL pinged by client on impression
%% 3. Rendering & Impression
App->>SDK: Render Ad (adm + ext + nURL + bURL)
activate SDK
SDK->>SDK: DISPLAYING AD
SDK-->>Exchange: Impression Detected
deactivate SDK
%% 4. Parallel tracker calls on impression
par Fire ext trackers
SDK->>T1: GET ext.imptrackers[0]
SDK->>T2: GET ext.imptrackers[1]
and Fire billing URL
SDK->>Exchange: GET bURL
and Fire final nURL
SDK->>Exchange: GET nURL
end
```
## Video Ad Scheme
```mermaid
sequenceDiagram
participant App
participant SDK as SDK Renderer
participant Exchange as BidMachine Exchange Server
participant DSP1 as DSP-1
participant DSP2 as DSP-2
participant Tracker1 as VAST Tracker 1
participant Tracker2 as VAST Tracker 2
%% 1. Ad Request & Auction
App->>Exchange: Ad Request
Exchange->>DSP1: Bid Request
Exchange->>DSP2: Bid Request
note over DSP1,DSP2: Auction
alt DSP-1 wins
Exchange->>DSP1: Winner notification
DSP1-->>Exchange: Bid Response • adm contains VAST XML with tags • nURL (win-notify) • bURL (billing)
else DSP-2 wins
Exchange->>DSP2: Winner notification
DSP2-->>Exchange: Bid Response • adm contains VAST XML with tags • nURL (delayed-notify) • bURL (billing)
end
Exchange-->>App: Bid Response (body)
%% 2. Notification schemes
note right of Exchange: Server-side win scheme • nURL pinged immediately on win • bURL held until impression
note right of App: Client-side delayed scheme • VAST trackers in adm • nURL pinged by client on impression
%% 3. Rendering & Impression
App->>SDK: Render ad (adm with VAST)
activate SDK
SDK->>SDK: DISPLAYING AD
SDK-->>Exchange: Impression detected
deactivate SDK
%% 4. Parallel tracker calls
par Fire VAST impression trackers
SDK->>Tracker1: GET https://tracker1.com
SDK->>Tracker2: GET https://tracker2.com
and Fire billing URL
SDK->>Exchange: GET bURL
and Fire final nURL
SDK->>Exchange: GET nURL
end
```
---
## Getting Started
Connect with high-quality inventory, global audiences, and achieve your campaign goals with precision.
:::note
Supported Open RTB versions: 2.3 and 2.5
:::
## Data Centers
BidMachine currently has four datacenters:
- **ASIA-PACIFIC**: Singapore
- **EUROPE**: Falkenstein, Germany
- **US-EAST**: New York, Washington
- **US-WEST**: Dallas, Texas
## Supported Ad Types
### Video Ads (VAST)
Can be rewarded or skippable. Supported dimensions:
1. 320×480
2. 480×320
3. 768×1024
4. 1024×768
Video ads also support the following end cards:
- Static Image
- HTML
- Playable HTML
### Static Ads (HTML, MRAID, MREC)
#### Banners
- 300×250 (MREC)
- 320×50 (phone)
- 728×90 (tablet)
#### Fullscreen Interstitials
Can be rewarded or skippable:
- 320×480 (phone)
- 480×320 (phone)
- 768×1024 (tablet)
- 1024×768 (tablet)
### Native Ads
Supported natively within the BidMachine SDK.
:::warning
If you want to identify **rewarded** traffic, refer to the fields `imp.video.ext.videotype` and `imp.banner.ext.bannertype`. Use the value `"rewarded"` for rewarded traffic.
:::
## Bid Request
BidMachine use `POST` for all Open RTB requests.
The request body must be a valid Open RTB JSON object. Bid Request body specification is described in [the next page](/dsp/bid-request/specification).
## Auction Type
BidMachine uses a **first-price** auction model. Bidders are expected to pay the full CPM amount they bid.
---
## Requirements
If you would like to be one of BidMachine Demand Partners, please review the details below:
- BidMachine support's mobile in-app publisher's inventory only
- BidMachine works on **CPM** business model
- **COPPA** compliant
- BidMachine Ad Exchange supports the Open RTB version `2.3` and `2.5`
- BidMachine's Data Centers are located in Germany, the US (Texas), and Singapore
- GDPR DPA: [Donwload the file](https://bidmachine-creatives.s3.amazonaws.com/dsp/DPA%2BEUMC+Demand+side_DSP+-+AppodealX+v.1.5.docx)
- BidMachine Ad Exchange Demand Policies: [Download the file](https://bidmachine-creatives.s3.amazonaws.com/dsp/BidMachine+Ad+Exchange+Demand+Policies_Final_06.24.2021.pdf)
If your DSP meets the requirements above please proceed to the Integration questionnaire.
For further information on the integration process, contact BidMachine Demand Team: [hi@bidmachine.io](mailto:hi@bidmachine.io)
---
## Adapter Bidding/Waterfall
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import JavaLabel from '@site/src/components/code-labels/java'
import KotlinLabel from '@site/src/components/code-labels/kotlin'
This guide shows you how to integrate the official BidMachine adapter for Google AdMob on Android.
:::info Waterfall Integration BETA
Waterfall integration is currently in beta. Please contact your BidMachine account manager for setup assistance and access.
:::
## Import the BidMachine SDK and Adapter
:::warning Version Compatibility
Failure to integrate the compatible BidMachine SDK and Google Mobile Ads SDK versions might lead to build issues.
:::
### Add BidMachine Repository
Add the BidMachine repository to your project-level `build.gradle` file:
```groovy title="build.gradle"
repositories {
maven {
url "https://artifactory.bidmachine.io/bidmachine"
}
}
```
### Add Dependencies
Add the following dependencies to your app-level `build.gradle` file:
}>
```kotlin title="build.gradle.kts"
dependencies {
implementation("com.google.android.gms:play-services-ads:25.3.0")
implementation("com.google.ads.mediation:bidmachine:3.7.0.0")
}
```
}>
```groovy title="build.gradle"
dependencies {
implementation 'com.google.android.gms:play-services-ads:25.3.0'
implementation 'com.google.ads.mediation:bidmachine:3.7.0.0'
}
```
## Additional Configuration
For complete console setup and integration instructions, see the [AdMob Console Setup (Official)](/sdk/admob/admob-bidding-console) page.
---
## Changelog
## Version 3.6.1.50 (April 20, 2026)
**Features**:
* Updated BidMachine version to 3.6.1
* Updated AdMob version to 25.2.0
## Version 3.5.0.49 (November 3, 2025)
**Features**:
* Updated BidMachine version to 3.5.0
* Updated AdMob version to 24.7.0
## Version 3.4.0.48 (August 13, 2025)
**Features**:
* Updated BidMachine version to 3.4.0
* Updated AdMob version to 24.5.0
## Version 3.3.0.47 (August 7, 2025)
**Bugfix**:
* Fix proguard
## Version 3.3.0.46 (July 15, 2025)
**Features**:
* Added `PlacementId`
* Updated AdMob version to 24.4.0
## Version 3.3.0.45 (May 29, 2025)
**Features**:
* Updated BidMachine version to 3.3.0
* Updated AdMob version to 24.3.0
## Version 3.2.1.44 (May 7, 2025)
**Bugfix**:
* Updated AdMob adapter to be compatible with both versions prior 24.0.0 and upper
## Version 3.2.1.43 (March 27, 2025)
**Features**:
* Updated AdMob version to 24.1.0
## Version 3.2.1.42 (March 24, 2025)
**Features**:
* Updated BidMachine version to 3.2.1
* Improved AdMob adapter errors
## Version 3.2.0.41 (February 20, 2025)
**Features**:
* Updated BidMachine version to 3.2.0
## Version 3.1.1.40 (January 10, 2025)
**Features**:
* Added Waterfall adapter
* Updated Native Ad integration
* Updated AdMob version to 23.6.0
## Version 3.1.1.39 (November 26, 2024)
**Features**:
* Updated BidMachine version to 3.1.1
* Updated AdMob version to 23.5.0
## Version 3.0.1.38 (September 19, 2024)
**Features**:
* Updated BidMachine version to 3.0.1
## Version 3.0.0.37 (August 22, 2024)
**Features**:
* Updated BidMachine version to 3.0.0
* Updated AdMob version to 23.3.0
## Version 2.7.0.36 (May 9, 2024)
**Features**:
* Updated Min Android SDK version to 21 due to AdMob update to 23.0.0.
* Updated BidMachine version to 2.7.0
* Updated AdMob version to 23.0.0
## Version 2.6.0.35 (April 5, 2024)
**Features**:
* Updated BidMachine version to 2.6.0
## Version 2.5.1.34 (March 1, 2024)
**Features**:
* Updated BidMachine version to 2.5.1
## Version 2.5.0.33 (February 16, 2024)
**Features**:
* Updated BidMachine version to 2.5.0
## Version 2.4.2.32 (February 1, 2024)
**Features**:
* Updated BidMachine version to 2.4.2
* Updated AdMob version to 22.6.0
## Version 2.4.0.31 (January 09, 2024)
**Features**:
* Removed Waterfall
## Version 2.4.0.30 (November 10, 2023)
**Features**:
* Updated BidMachine version to 2.4.0
* Updated AdMob version to 22.5.0
## Version 2.3.3.29 (October 30, 2023)
**Features**:
* Updated AdMob version to 22.4.0
## Version 2.3.3.28 (September 4, 2023)
**Features**:
* Updated BidMachine version to 2.3.3
* Updated AdMob version to 22.3.0
## Version 2.3.2.27 (August 3, 2023)
**Features**:
* Updated BidMachine version to 2.3.2
* Updated AdMob version to 22.2.0
## Version 2.2.0.26 (May 22, 2023)
**Features**:
* Updated BidMachine version to 2.2.0
* Updated AdMob version to 22.1.0
## Version 2.1.13.25 (May 10, 2023)
**Features**:
* Updated AdMob version to 22.0.0
## Version 2.1.13.24 (May 10, 2023)
**Features**:
* Updated BidMachine version to 2.1.13
* Updated AdMob version to 21.5.0
## Version 1.9.10.23 (August 22, 2022)
**Features**:
* Updated BidMachine version to 1.9.10
* Updated AdMob version to 21.1.0
## Version 1.9.4.22 (June 6, 2022)
**Features**:
* Deprecated CustomEvent and switched to [Adapter](https://developers.google.com/android/reference/com/google/android/gms/ads/mediation/Adapter)
* Updated waterfall sample
## Version 1.9.4.21 (May 30, 2022)
**Features**:
* Updated BidMachine version to 1.9.4
* Updated AdMob version to 21.0.0
## Version 1.9.3.20 (March 31, 2022)
**Features**:
* Updated BidMachine version to 1.9.3
## Version 1.9.2.19 (March 16, 2022)
**Features**:
* Updated BidMachine version to 1.9.2
* Updated AdMob version to 20.6.0
## Version 1.9.1.18 (February 11, 2022)
**Features**:
* Updated BidMachine version to 1.9.1
## Version 1.9.0.17 (February 01, 2022)
**Features**:
* Updated BidMachine version to 1.9.0
## Version 1.8.3.16 (December 29, 2021)
**Features**:
* Updated BidMachine version to 1.8.3
## Version 1.8.2.15 (December 23, 2021)
**Features**:
* Updated BidMachine version to 1.8.2
## Version 1.8.1.14 (December 16, 2021)
**Features**:
* Updated BidMachine version to 1.8.1
* Updated AdMob version to 20.5.0
## Version 1.7.1.13 (March 30, 2021)
**Features**:
* Updated BidMachine version to 1.7.1
* Updated AdMob version to 19.8.0
## Version 1.6.4.12 (March 18, 2021)
**Features**:
* Updated AdMob version to 19.8.0
## Version 1.6.4.11 (March 4, 2021)
**Features**:
* Updated BidMachine version to 1.6.4
## Version 1.6.3.10 (February 2, 2021)
**Features**:
* Updated AdMob version to 19.7.0
## Version 1.6.3.9 (January 18, 2021)
**Features**:
* Updated BidMachine version to 1.6.3
## Version 1.6.1.8 (November 3, 2020)
**Features**:
* Updated BidMachine version to 1.6.1
* Updated AdMob version to 19.5.0
## Version 1.5.2.7 (August 3, 2020)
**Features**:
* Updated BidMachine version to 1.5.2
* Updated AdMob version to 19.3.0
## Version 1.5.1.6 (July 21, 2020)
**Features**:
* Added HeaderBidding implementation
## Version 1.5.1.5 (July 16, 2020)
**Features**:
* Updated BidMachine version to 1.5.1
* Updated AdMob version to 19.2.0
## Version 1.4.4.4 (June 8, 2020)
**Features**:
* Updated BidMachine version to 1.4.4
* Updated AdMob version to 19.1.0
## Version 1.4.0.3 (December 2, 2019)
**Features**:
* Added Native Ad type
## Version 1.3.0.2 (August 14, 2019)
**Features**:
* Updated BidMachine version to 1.3.0
* Added availability to pass `mediation_config` and `endpoint` parameters into BidMachine SDK via AdMob's `localExtras` or `serverParameters`.
---
## Waterfall Custom Adapter
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import Admonition from '@theme/Admonition'
import JavaLabel from '@site/src/components/code-labels/java'
import KotlinLabel from '@site/src/components/code-labels/kotlin'
import SwiftLabel from '@site/src/components/code-labels/swift'
import ObjCLabel from '@site/src/components/code-labels/objc'
:::danger DEPRECATED - Use Official AdMob Adapter
This custom adapter is **deprecated**. BidMachine is now an official Google AdMob partner.
**Please use the [official AdMob adapter](/sdk/admob/admob-bidding-console) instead** for better performance, official support, and seamless integration with AdMob.
:::
The adapter supports custom waterfall integration for the next ad formats:
- Banner
- Interstitial
- Rewarded
- Native
:::success Full Technical Documentation
To get full documentation and samples please refer to the GitHub [Android](https://github.com/bidmachine/BidMachine-Android-admob-adapter-example).
:::
## Integration
:::info
Min Android SDK version - 23 (6.0, Marshmallow)
:::
```groovy title="build.gradle"
repositories {
maven {
url "https://artifactory.bidmachine.io/bidmachine"
}
}
```
In your `build.gradle` file add the following dependency which includes the BidMachine adapter for use within AdMob platform:
```groovy title="build.gradle"
dependencies {
// Add BidMachine SDK dependency
implementation "io.bidmachine:ads:3.6.1"
// Add BidMachine SDK AdMob Adapter dependency
implementation "io.bidmachine:ads.adapters.admob:3.6.1.50"
// Add AdMob SDK dependency
implementation "com.google.android.gms:play-services-ads:25.2.0"
}
```
## Initialization
Waterfall integration does not require `BidMachineSdk` initialization code, as it is triggered automatically as part of the `MobileAds` initialization.
}>
```java
MobileAds.initialize(context, new OnInitializationCompleteListener() {
@Override
public void onInitializationComplete (InitializationStatus initializationStatus){
// Request ads
}
});
```
}>
```kotlin
MobileAds.initialize(context) {
// Optionally, enable test mode and logging
BidMachine.setTestMode(true)
BidMachine.setLoggingEnabled(true)
}
```
## Logging and Test Mode
:::warning
All parameters for BidMachine SDK must be set before starting AdMob SDK.
:::
}>
```java
BidMachine.setTestMode(true);
BidMachine.setLoggingEnabled(true);
```
}>
```kotlin
BidMachine.setTestMode(true)
BidMachine.setLoggingEnabled(true)
```
:::warning
Don't forget to remove `setTestMode()` before releasing to production!
:::
## Additional Configuration
- [Advanced SDK settings](/sdk/general/android/advanced/)
- [Data Privacy settings](/sdk/general/android/privacy/)
---
## Console Setup
import Image from "@theme/IdealImage";
## Manual Setup
### Bidding Adapter
BidMachine's bidding adapter enables real-time bidding integration with AdMob. This setup allows BidMachine to participate in AdMob's bidding auctions.
:::important Requirements
- Android API level 23 or higher
- BidMachine adapter version 3.4.0.1 or later (Use the latest available BidMachine adapter version for all formats)
- Latest Google Mobile Ads SDK
:::
#### Step 1: BidMachine Dashboard Configuration
1. Navigate to the **Source** tab in your BidMachine dashboard and select **Edit**. Copy the **Integration ID** for later use in the AdMob console.
2. Click **Add Placement** to create new placements
:::tip Placement Management API
You can also create and manage placements programmatically using the [Placement Management API](/api/bidmachine-placement-management-api) — useful when provisioning placements at scale.
:::
:::note Bundle Identifier Format
When setting up your mediation group, use the appropriate bundle identifier format:
- **Android apps**: Use alphabetic bundle identifier (e.g., `com.example.app`)
- **iOS apps**: Use numeric app ID (e.g., `123456789`)
:::
3. Save your changes and note the **Placement ID** for later use
4. Access the **app-ads.txt** tab in the BidMachine dashboard, copy the content, and append it to your website's app-ads.txt file
#### Step 2: AdMob Console Setup
1. Sign into your [AdMob account](https://apps.admob.com/)
2. Navigate to **Mediation** and either create a new mediation group or edit an existing one
3. Configure ad format and platform settings
4. Select **Add ad source** under the **Bidding** card
5. Locate and choose **BidMachine** from the available networks
6. Establish the partnership agreement if prompted
7. Add mapping with your **Placement ID** from the BidMachine dashboard
8. Add BidMachine to GDPR and US state regulations ad partners lists per AdMob's European and US state regulations settings
#### Step 3: Enable Secure Signals & User Consent
:::danger Required — most common cause of "no bids"
BidMachine **will not bid** unless **Secure Signal sharing** is enabled and BidMachine is allowed under your **User Consent** settings in the AdMob/GAM console. These toggles are **off by default** and are the most frequent reason publishers see no fill after an otherwise correct setup. Verify both before troubleshooting anything else.
:::
**1. Enable Secure Signal sharing**
Secure signals are the encrypted bidding parameters BidMachine needs to participate in the auction. They must be explicitly enabled for the BidMachine bidder:
1. Sign in to your [Google Ad Manager](https://admanager.google.com/) account
2. Go to **Delivery → Bidders**, open **SDK Bidding**, and select **BidMachine**
3. Under **Secure signal sharing (required)**, check whether each item shows **Enabled** or **Disabled**
4. If anything is marked **Disabled**, click the link for each item to enable the **library** and the **sharing of signals** to BidMachine
5. Confirm signals are being passed using **Delivery Tools** or **Ad Inspector** (the *Buyer generated data* field in the third-party bidding parameters should show a substantial character count)
:::info Google reference
Follow Google's official guide for exact screenshots and current console paths: [Verify your SDK Bidding setup → Enable secure signals](https://support.google.com/admanager/answer/14863770?hl=en#enable-secure-signals).
:::
**2. Allow BidMachine under User Consent settings**
1. In the AdMob console, open **Privacy & messaging** and review your **European regulations (GDPR)** and **US state regulations** settings
2. Make sure **BidMachine** is added to your list of allowed ad partners / commonly used ad partners for each applicable regulation
3. If BidMachine is not on the consent vendor list, no consent signal will be passed and bidding will fail
:::note App-side requirement
The console settings above only work if your app also forwards consent correctly — see [Step 4: Privacy Implementation](#step-4-privacy-implementation) below.
:::
#### Step 4: Privacy Implementation {#step-4-privacy-implementation}
BidMachine automatically reads GDPR consent set by consent management platforms including UMP SDK. Similarly, it reads GPP consent automatically for US state compliance.
Ensure you have implemented a Consent Management Platform (CMP) in your app according to AdMob's privacy requirements.
#### Step 5: Testing
1. Register your test device for AdMob
2. Enable test mode in BidMachine's SDK documentation
3. Use Ad Inspector's single ad source testing feature to verify BidMachine ads
4. Disable test modes before production release
### Waterfall Adapter BETA
:::info Contact Your Account Manager
Waterfall integration is currently in beta. Please contact your BidMachine account manager for setup assistance and access.
:::
BidMachine waterfall integration allows you to add BidMachine as a custom event in your AdMob mediation waterfall with specific price points.
:::important Adapter Compatibility
Use Use the latest available BidMachine adapter version for all formats.
:::
#### Manually
:::note Multiple Placements
To set up multiple placements, repeat the setup process for each placement with its corresponding Placement ID.
:::
##### 1. BidMachine Dashboard Configuration
1. Navigate to the **Source** tab in your BidMachine dashboard and select **Edit**
2. Click **Add Placement** to create new placements (or create them programmatically via the [Placement Management API](/api/bidmachine-placement-management-api))
3. Save your changes and note the **Placement ID** for later use
4. Access the **app-ads.txt** tab in the BidMachine dashboard, copy the content, and append it to your website's app-ads.txt file
##### 2. AdMob Console Setup
1. Sign into your [AdMob account](https://apps.admob.com/)
2. Navigate to **Mediation** and either create a new mediation group or edit an existing one
3. Configure ad format and platform settings
4. Select **Add Ad Source** under the waterfall section
5. Enter the **eCPM value** for this price point
6. Locate and choose **BidMachine** from the available networks
7. Add mapping with your **Placement ID** from the BidMachine dashboard
8. Click **Done** to save the ad source
9. Repeat steps 4-8 for each price point you want to add
**Recommended Price Points:**
| Banners/Native/Mrec | Skippable (Int + Video) | Non-Skippable (Rewarded) |
|---------------------|-------------------------|---------------------------|
| `0.1`, `0.3`, `0.4`, `0.5`, `1.0`, `1.5`, `3.0` | `1.0`, `5.0`, `10.0`, `20.0`, `30.0`, `40.0`, `70.0`, `100.0` | `1.0`, `5.0`, `10.0`, `20.0`, `30.0`, `40.0`, `70.0`, `100.0`, `200.0` |
:::note Waterfall Behavior
Not all ad units will be called in waterfall but only the ones that match BidMachine bid prices.
:::
##### 3. Privacy Implementation
BidMachine automatically reads GDPR consent set by consent management platforms including UMP SDK. Similarly, it reads GPP consent automatically for US state compliance.
Ensure you have implemented a Consent Management Platform (CMP) in your app according to AdMob's privacy requirements.
##### 4. Finalizing Setup
Once you are done creating ad sources, you should see the final waterfall with your networks and newly created BidMachine ad sources.
##### 6. Testing
1. Register your test device for AdMob
2. Enable test mode in BidMachine's SDK documentation
3. Use Ad Inspector to verify BidMachine waterfall ads at different price points
4. Disable test modes before production release
---
## Console Setup(Admob)
import Image from "@theme/IdealImage";
:::danger DEPRECATED - Use Official AdMob Adapter
This custom adapter setup is **deprecated**. BidMachine is now an official Google AdMob partner.
**Please use the [official AdMob adapter](/sdk/admob/admob-bidding-console) instead** for better performance, official support, and seamless integration with AdMob.
:::
Regular BidMachine waterfall integration. It requires adding specific **Custom Events** for selected **Mediation Group**.
:::important Adapter Compatibility
BidMachine waterfall integration has been supported since v`3.1.1.40` for Android and v`3.1.1.2` for iOS.
:::
## Waterfall Adapter
### Automatically (Chrome extension)
1. Install the [BidMachine Mediation Helper Extension](https://chromewebstore.google.com/detail/bhbbahnainkpbhpknaegjkmgffojffkb?utm_source=item-share-cb)
2. Open the extension and go to the Google AdMob dashboard. The extension will detect your account and find mediation groups associated with it.
3. Select a **Mediation Group** where you want to add BidMachine Prebid.
4. Fill out your data:
- **Source Id** - Source Id from your account
- **Integration type** - `Waterfall` type should be selected
- Keep overwriting existing BidMachine Custom Events checked if you want the extension to replace previously created Custom Events for BidMachine (both prebid and waterfall)
- **Compare operator** - select comparator from the dropdown menu
- **Price Points** - an array of Price Points used for Custom Events. Can be modified manually
5. Press the `Create` button, and you're all set.
### Manually
1. Creating BidMachine custom events within mediation group
Go to Google AdMob dashboard and choose mediation group where you want to create BidMachine ad sources.
Go inside chosen mediation group and start creating BidMachine custom events with the prices you want to use
2. Setting up Class name and parameters for custom events
Enter the label of ad source and set up the price and click Continue
Then in the next window set up class name and class parameters according to the following table
| Platform | Ad Type | Class Name
| :------- | :------------- | :------------------------------------------------------------------------- |
| iOS | Banner | `BidMachineWaterfallCustomEventBanner` |
| iOS | Interstitial | `BidMachineWaterfallCustomEventInterstitial` |
| iOS | Rewarded Video | `BidMachineWaterfallCustomEventRewarded` |
| iOS | Native | `BidMachineWaterfallCustomEventNativeAd` |
| Android | Banner | `com.google.ads.mediation.bidmachine.waterfall.BidMachineWaterfallAdapter` |
| Android | Interstitial | `com.google.ads.mediation.bidmachine.waterfall.BidMachineWaterfallAdapter` |
| Android | Rewarded Video | `com.google.ads.mediation.bidmachine.waterfall.BidMachineWaterfallAdapter` |
| Android | Native | `com.google.ads.mediation.bidmachine.waterfall.BidMachineWaterfallAdapter` |
:::note Class names
On Android, the class name is the same for all ad types, so you can use the same class name for all ad sources.
On iOS, you need to specify the class name according to the ad type.
:::
Parameters description:
| Parameter name | Description | Type | Requirements | Example |
| :--------------- | :--------------------------- | :----- | :---------- | :------------------------------ |
| `source_id` | Your Source Id | String | Required | `"source_id":"your_source_id"` |
| `bm_pf` | eCPM of BidMachine ad source | Double | Required | `"bm_pf":"1.0"` |
| `placement_id` | Placement ID from [BidMachine Placement](/dashboard/placement). Placements can also be managed programmatically via the [Placement Management API](/api/bidmachine-placement-management-api). | UUID | Optional | `"placement_id":"your_placement_id"` |
:::warning JSON format
Parameters should be in JSON format, so make sure to use double quotes for keys and values. For example:
```
{"bm_pf":"1.00", "source_id": "your_source_id", "placement_id": "your_placement_id"}
```
:::
Example of filling Class name and parameters for iOS Banner:
:::tip Price Floors
In parameters in `bm_pf` field - specify exactly the same price as you used for creating ad source
:::
Price Points for BidMachine ad sources can be set up in the following way:
| Banners/Native/Mrec | Skippable (Int + Video) | Non-Skippable (Rewarded) |
|---------------------|-------------------------|---------------------------|
| `0.1`, `0.3`, `0.4`, `0.5`, `1.0`, `1.5`, `3.0` | `1.0`, `5.0`, `10.0`, `20.0`, `30.0`, `40.0`, `70.0`, `100.0` | `1.0`, `5.0`, `10.0`, `20.0`, `30.0`, `40.0`, `70.0`, `100.0`, `200.0` |
:::note
Not all ad units will be called in waterfall but only the one that matches BidMachine bid prices.
:::
When you are finished with filling all needed info - click `Done`
3. Finalising setup
You can create several ad sources within same mediation group. Once you are done with creating them - you should see final waterfall with your networks and newly created BidMachine ad sources.
If you want to change prices of created ad sources - you should not only change eCPM of it but also change `bm_pf` value in parameters of it.
---
## Adapter Bidding/Waterfall(Ios)
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
This guide shows you how to integrate the official BidMachine adapter for Google AdMob on iOS.
:::info Waterfall Integration BETA
Waterfall integration is currently in beta and requires adapter version **3.7.1.1** or higher. Please contact your BidMachine account manager for setup assistance and access.
:::
## Import the BidMachine SDK and Adapter
:::warning Version Compatibility
Failure to integrate the compatible BidMachine SDK and Google Mobile Ads SDK versions might lead to build issues.
:::
Requires minimum adapter version 3.6.0.0.
1. In Xcode, select **File > Add Package Dependencies...**
2. Enter this package URL: `https://github.com/googleads/googleads-mobile-ios-mediation-bidmachine.git`
3. Set **Dependency Rule** to **Branch**
4. Enter `main` in the text field
Add this line to your Podfile:
```ruby title="Podfile"
pod 'GoogleMobileAdsMediationBidMachine', '>= 3.7.1.1'
```
Run:
```bash
pod install --repo-update
```
1. Download the latest BidMachine SDK for iOS and link all `.xcframework` files and bundles
2. Download the latest BidMachine adapter from the Changelog section and link `BidMachineAdapter.xcframework` in your project
## Additional Configuration
For complete console setup and integration instructions, see the [AdMob Console Setup (Official)](/sdk/admob/admob-bidding-console) page.
---
## Changelog(Ios)
## Version 3.6.0.1 (Apr 27th, 2026)
- Downgraded 'Google-Mobile-Ads-SDK' to '~> 13.0'
- 'BidMachine', '~> 3.6.0'
## Version 3.6.0.0 (Apr 17th, 2026)
- Fix Native Ad clicks
- Update 'Google-Mobile-Ads-SDK' to '13.2.0'
- Update 'BidMachine' to '~> 3.6.0'
## Version 3.5.0.1 (Nov 6th, 2025)
- Update banner ad sizes mapping logic
- Update 'Google-Mobile-Ads-SDK' to '12.12.0'
- Update 'BidMachine' to '3.5.0'
## Version 3.4.0.0 (Aug 13th, 2025)
- Update 'Google-Mobile-Ads-SDK' to '12.9.0'
- Update 'BidMachine' to '3.4.0'
## Version 3.3.0.3 (Jul 24th, 2025)
- Fixed an issue with placement comparison for Prebid integrations
## Version 3.3.0.2 (July 17, 2025)
**Features**:
- Added `Placement ID` support
## Version 3.3.0.1 (Jul 7th, 2025)
- Update 'Google-Mobile-Ads-SDK' to '12.6.0'
## Version 3.3.0.0 (Jun 9, 2025)
- BidMachine SDK 3.3.0
## Version 3.2.1.0 (March 24, 2025)
- BidMachine SDK 3.2.1
- Google-Mobile-Ads-SDK 12.2.0
## Version 3.2.0.1 (March 5, 2025)
- Google-Mobile-Ads-SDK 12.1.0
## Version 3.2.0.0 (February 10, 2025)
- BidMachine SDK 3.2.0
## Version 3.1.1.2 (January 10, 2025)
- Added Waterfall adapter
---
## Waterfall Custom Adapter(Ios)
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import Admonition from '@theme/Admonition'
import JavaLabel from '@site/src/components/code-labels/java'
import KotlinLabel from '@site/src/components/code-labels/kotlin'
import SwiftLabel from '@site/src/components/code-labels/swift'
import ObjCLabel from '@site/src/components/code-labels/objc'
:::danger DEPRECATED - Use Official AdMob Adapter
This custom adapter is **deprecated**. BidMachine is now an official Google AdMob partner.
**Please use the [official AdMob adapter](/sdk/admob/admob-bidding-console) instead** for better performance, official support, and seamless integration with AdMob.
:::
The adapter supports custom waterfall integration for the next ad formats:
- Banner
- Interstitial
- Rewarded
- Native
:::success Full Technical Documentation
To get full documentation and samples please refer to the GitHub [Android](https://github.com/bidmachine/BidMachine-Android-admob-adapter-example) or [iOS](https://github.com/bidmachine/BidMachine-Google-Mobile-Ads-iOS-Adapters).
:::
## Integration
In your **Podfile** file add the following dependency which includes the BidMachine adapter for use within AdMob platform:
```ruby title="Podfile"
target 'Target' do
project 'Project.xcodeproj'
pod 'BidMachineAdMobAdapter', '~> 3.6.0.0'
end
```
## Initialization
The BidMachineAdMobAdapter starting 3.1.1.2 version offers robust support for waterfall integration. This integration type require to configure mediation groups in AdMob account by adding BidMachine Custom Events and Mappings.
Waterfall integration does not require BidMachineSdk initialization code, as it is triggered automatically as part of the MobileAds initialization.
However, if you need to configure additional BidMachineSdk settings, refer to the Logging and Test Mode below.
## Logging and Test Mode
:::warning
All parameters for BidMachine SDK must be set before starting AdMob SDK.
:::
}>
```swift
BidMachineSdk.shared.populate { builder in
builder
.withTestMode(true)
.withLoggingMode(true)
.withBidLoggingMode(true)
.withEventLoggingMode(true)
}
MobileAds.shared.start(completionHandler: nil)
```
:::warning
Don't forget to remove `.withTestMode()` before releasing to production!
:::
}>
```objc
[BidMachineSdk.shared populate:^(id builder) {
[builder withTestMode:YES];
[builder withLoggingMode:YES];
[builder withBidLoggingMode:YES];
[builder withEventLoggingMode:YES];
}];
[[GADMobileAds sharedInstance] startWithCompletionHandler:^(GADInitializationStatus * _Nonnull status) { }];
```
:::warning
Don't forget to remove `[builder withTestMode:];` before releasing to production!
:::
## Additional Configuration
- [Advanced SDK settings](/sdk/general/ios/advanced/)
- [Data privacy settings](/sdk/general/ios/privacy/)
---
## Overview
import Step from '@site/src/components/mdx/step'
import Stepper from '@site/src/components/mdx/stepper'
This page gives you step-by-step instructions for how you set BidMachine live as an ad network on the AdMob Mediation platform.
## How to Create a BidMachine Account?
Create a BidMachine Account at [bidmachine.io](https://bidmachine.io/#sign-up).
Upon registration, an activation email containing instructions will be sent
to the email address you've provided. Please use the provided instructions
to activate your account.
## Testing instructions
Before deploying the BidMachine SDK and adapter to your live application, you can perform testing with the test mode. This will guarantee a high fill rate (99.99%) during the integration testing process, ensuring that the implementation is functioning correctly. It is crucial to disable the test mode before going live, as failing to do so will result in financial loss.
## Revenue Reports
You will be provided with a dashboard, please contact your account manager who will share the credentials with you.
---
## Advanced Settings
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
## Global Settings
### Logs
BidMachine SDK provides a set of logging options to help you debug and monitor the SDK's behavior.
You can enable or disable different types of logs, such as general logs, bid logs, and event logs.
}>
```java
BidMachine.setLoggingEnabled(boolean);
```
}>
```kotlin
BidMachine.setLoggingEnabled(Boolean)
```
### Test Mode
BidMachine SDK can be configured to run in test mode, which is useful for testing and debugging purposes.
}>
```java
BidMachine.setTestMode(boolean);
```
}>
```kotlin
BidMachine.setTestMode(Boolean)
```
:::warning
Test mode should be disabled in production.
:::
### Location
SDK can automatically track user device location to serve better ads.
The SDK never requests location permissions itself: it reads the device location only if your app has already obtained a location permission from the user.
With `ACCESS_COARSE_LOCATION`, approximate location is collected; with `ACCESS_FINE_LOCATION`, precise location is collected — declare this accordingly in your Google Play Data safety form (see [App Privacy Details on Google Play](./app-privacy-details.mdx)).
To make it work for **Android 6.0**, you should request `android.permission.ACCESS_COARSE_LOCATION` and `android.permission.ACCESS_FINE_LOCATION`:
}>
```java
ActivityCompat.requestPermissions(@NonNull Activity, new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
}, REQ_CODE);
```
}>
```kotlin
ActivityCompat.requestPermissions(Activity, arrayOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
), REQ_CODE)
```
### Publisher Parameters
The publisher info is used to provide information about the publisher of the app.
This information is used for targeting and reporting purposes.
}>
```java
BidMachine.setPublisher(@Nullable Publisher);
```
}>
```kotlin
BidMachine.setPublisher(Publisher?)
```
| Param | Type | Description |
| :------- | :----- | :------------------------- |
| Id | String | Publisher ID |
| Name | String | Publisher name |
| Domain | String | Publisher domain |
| Category | String | Publisher content category |
Code Example:
}>
```java
Publisher publisher = new Publisher.Builder()
.setId(@Nullable String)
.setName(@Nullable String)
.setDomain(@Nullable String)
.addCategory(@Nullable String)
.addCategories(@Nullable List)
.build();
// Sets publisher information
BidMachine.setPublisher(publisher);
```
}>
```kotlin
val publisher = Publisher.Builder()
.setId(String?)
.setName(String?)
.setDomain(String?)
.addCategory(String?)
.addCategories(List?)
.build()
// Sets publisher information
BidMachine.setPublisher(publisher)
```
### Targeting Parameters
The targeting info is used to provide information about the user and the app.
}>
```java
TargetingParams targetingParams = new TargetingParams()
.setUserId(@Nullable String)
.setGender(@Nullable Gender)
.setBirthdayYear(@Nullable Integer)
.setKeywords(@Nullable String[])
.setDeviceLocation(@Nullable Location)
.setCountry(@Nullable String)
.setCity(@Nullable String)
.setZip(@Nullable String)
.setStoreUrl(@Nullable String)
.setStoreCategory(@Nullable String)
.setStoreSubCategories(@Nullable String[])
.setFramework(@Nullable String)
.setPaid(@Nullable Boolean)
.setExternalUserIds(@Nullable List)
.addBlockedAdvertiserIABCategory(@NonNull String)
.addBlockedAdvertiserDomain(@NonNull String)
.addBlockedApplication(@NonNull String);
```
}>
```kotlin
val targetingParams = TargetingParams()
.setUserId(String?)
.setGender(Gender?)
.setBirthdayYear(Int?)
.setKeywords(vararg String?)
.setDeviceLocation(Location?)
.setCountry(String?)
.setCity(String?)
.setZip(String?)
.setStoreUrl(String?)
.setStoreCategory(String?)
.setStoreSubCategories(vararg String?)
.setFramework(String?)
.setPaid(Boolean?)
.setExternalUserIds(List?)
.addBlockedAdvertiserIABCategory(String)
.addBlockedAdvertiserDomain(String)
.addBlockedApplication(String)
```
`TargetingParams` can be passed with 2 ways:
- Through global parameters:
}>
```java
BidMachine.setTargetingParams(targetingParams);
```
}>
```kotlin
BidMachine.setTargetingParams(targetingParams)
```
- Through ad request builder:
}>
```java
adRequestBuilder.setTargetingParams(targetingParams);
```
}>
```kotlin
adRequestBuilder.setTargetingParams(targetingParams)
```
You can combine global parameters with regular. If you set Global `TargetingParams` using `UserId`, and then make a request using `TargetingParams` with `Gender` set, both requests will be merged and the resulting `TargetingParams` will include both `UserId` and `Gender`.
:::tip Priority of Targeting Parameters
Priority is given to the `AdRequest` parameters.
:::
## Auction Request Settings
### Price Floor Parameters
The price floor info is used to set a minimum price for the ad unit, you can pass multiple price floors for one ad request.
:::tip Price Floor Currency
The price floor is always in the US dollars.
:::
If you use the method with only **Price** provided `PriceFloorParams.addPriceFloor(Double)`,
the **Id** will be generated using `UUID.randomUUID()`.
}>
```java
PriceFloorParams priceFloorParams = new PriceFloorParams()
// Set Bid Price, in this case id will be generated
.addPriceFloor(double)
// Set Bid Id and Price
.addPriceFloor(@NonNull String, double);
```
}>
```kotlin
val priceFloorParams = PriceFloorParams()
// Set Bid Price, in this case id will be generated
.addPriceFloor(Double)
// Set Bid Id and Price
.addPriceFloor(String, Double)
```
| Parameter | Type | Description |
| :-------- | :----- | :----------------------- |
| Id | String | Unique floor identifier. |
| Price | double | Floor price |
To set up price floor parameters for ad request use `setPriceFloorParams` method from `AdRequest` builder according to ads type.
}>
```java
adRequestBuilder.setPriceFloorParams(priceFloorParams);
```
}>
```kotlin
adRequestBuilder.setPriceFloorParams(priceFloorParams)
```
## Placement Settings
### Custom Parameters
You can pass custom parameters in the placement object to be sent to the server.
Custom parameters is a dictionary of key-value pairs that can be used for targeting or reporting purposes.
}>
```java
CustomParams customParams = new CustomParams()
.addParam(@NonNull String, @NonNull String)
.addParams(@NonNull Map);
```
}>
```kotlin
val customParams = CustomParams()
.addParam(String, String)
.addParams(Map)
```
To set up custom parameters for ad request use `setCustomParams` method from `AdRequest` builder according to ads type.
}>
```java
adRequestBuilder.setCustomParams(customParams);
```
}>
```kotlin
adRequestBuilder.setCustomParams(customParams)
```
## Auction Info
The auction info provides details about the ad auction,
including bid ID, creative ID, deal ID, campaign ID,
demand source, price, and custom parameters.
You can get `AuctionResult` in two ways:
- Through `AdRequestListener`. Use `AuctionResult` from `onRequestSuccess` callback
}>
```java
adRequestBuilder.setListener(new .AdRequestListener() {
@Override
public void onRequestSuccess(@NonNull adRequest,
@NonNull AuctionResult auctionResult) {
// Use AuctionResult from onRequestSuccess callback
}
});
```
}>
```kotlin
adRequestBuilder.setListener(object : .AdRequestListener {
override fun onRequestSuccess(adRequest: ,
auctionResult: AuctionResult) {
// Use AuctionResult from onRequestSuccess callback
}
});
```
- Through getter. Each `AdRequest` has an option to retrieve auction result information after it has been loaded.
}>
```java
adRequest.getAuctionResult();
```
}>
```kotlin
adRequest.auctionResult
```
| Parameter | Type | Description | Sample |
| ---------------- | ---------------------- | ------------------------------------------------------------------------------------------------ | --------------------------------------------------- |
| Id | String | Winner bid ID provided in the request. | `cc5bd14b-aaef-4037-b4f8-879913366e3c` |
| Demand Source | String | Winner advertising source name. | `BidMachine Test` |
| Price | double | Winner price expressed as CPM. | `0.023` |
| Deal | String | Id of Price Floor. | `d6f61bf9-11a8-4172-a77d-4b1ff85a727f` |
| Creative Id | String | Winner creative id. | `123.13579` |
| CID | String | Winner Campaign ID or other similar grouping of brand-related ads. | `123.13587` |
| Ad Domain | Array of String | Winner advertiser domain (top two levels only, e.g., “ford.com”). | `["sample1.com", "sample2.com"]` |
| Network Key | String | Winner network key. This network will be loaded. | `mraid` |
| Network Params | Map, String - String | Client parameters of winner networks. | — |
| Creative Format | Enum | `CreativeFormat`, one of: Banner, Video, Native. | `CreativeFormat.Video` |
| Custom Params | Map, String - String | Map that contains additional information about the response. | — |
## Win/Loss notifications
Call `notifyMediationWin`/`notifyMediationLoss` on the AdRequest instance when BidMachine wins/loses the mediation among networks.
- Win notification:
}>
```java
adRequest.notifyMediationWin();
```
}>
```kotlin
adRequest.notifyMediationWin()
```
- Loss notification:
}>
```java
adRequest.notifyMediationLoss("", );
// or
adRequest.notifyMediationLoss();
```
}>
```kotlin
adRequest.notifyMediationLoss("", )
// or
adRequest.notifyMediationLoss()
```
---
## App Privacy Details On Google Play
# App Privacy Details on Google Play
This document outlines the types of user data the app handles, whether we collect it, and relevant remarks for each category.
## Data Collected
The app does collect the following data types under specified conditions:
- **Device ID**
Collected by the BidMachine SDK
- **Advertising Data**
Collected by the BidMachine SDK
- **Other Data Types**
The BidMachine SDK may also collect:
- **Technical device information** (e.g., device type, operating system, browser)
- **Other device information** (e.g., smartphone vs. tablet)
- **Network information** (e.g., network provider)
- **Carrier user ID** (a unique number assigned by the network provider)
## Data Collected Conditionally (Optional)
These data types are collected only if the host app has obtained the corresponding location permission from the user. The BidMachine SDK never requests location permissions itself:
- **Precise Location**
Optional — collected by the BidMachine SDK only if the host app has obtained the `ACCESS_FINE_LOCATION` permission from the user. The SDK does not request this permission itself.
- **Coarse Location**
Optional — collected by the BidMachine SDK if the host app has obtained the `ACCESS_COARSE_LOCATION` permission.
## Data Not Collected
Below is a list of data types that the app does **not** collect:
- **Name**
- **Email Address**
- **Phone Number**
- **Physical Address**
- **Other User Contact Info**
- **Health**
- **Fitness**
- **Payment Info**
- **Credit Info**
- **Other Financial Info**
- **Sensitive Info**
- **Contacts**
- **Emails or Text Messages**
- **Photos or Videos**
- **Audio Data**
- **Gameplay Content**
- **Other User Content**
- **Browsing History**
- **Search History**
- **User ID**
- **Purchase History**
- **Other Usage Data**
- **Other Diagnostic Data**
---
## Banner / MREC Ads
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
## Ad Request
### Placement
Create placement configuration using `AdPlacementConfig.bannerBuilder()` with `BannerAdSize`, placement id and other parameters.
}>
```java
AdPlacementConfig config = AdPlacementConfig.bannerBuilder()
.withPlacementId(...) // Set placement id
.withCustomParams(...) // Set custom parameters
.build();
BannerRequest.Builder bannerRequestBuilder = new BannerRequest.Builder(config)
.setTargetingParams(...) // Set TargetingParams instance
.setPriceFloorParams(...) // Set price floor parameters
.setLoadingTimeOut(...) // Set loading timeout in milliseconds
```
}>
```kotlin
val config = AdPlacementConfig.bannerBuilder()
.withPlacementId(...) // Set placement id
.withCustomParams(...) // Set custom parameters
.build()
val bannerRequestBuilder = BannerRequest.Builder(config)
.setTargetingParams(...) // Set TargetingParams instance
.setPriceFloorParams(...) // Set price floor parameters
.setLoadingTimeOut(...) // Set loading timeout in milliseconds
```
#### BannerAdSize
`BannerAdSize` is a required parameter for banner placement:
| Type | Size | Description |
| :---------------------------| :-------| :----------------------------------|
| `BannerAdSize.Banner` | 320x50 | Standard banner size |
| `BannerAdSize.Leaderboard` | 728x90 | Leaderboard banner size for tablets|
| `BannerAdSize.MediumRectangle` | 300x250 | Medium rectangle (MREC) banner |
#### Adaptive Banners
You can create adaptive banners with custom width and maximum height:
}>
```java
// Adaptive banner with width 350 and max height 100
BannerAdSize adaptiveSize = BannerAdSize.adaptive(350, 100);
AdPlacementConfig config = AdPlacementConfig.bannerBuilder(adaptiveSize)
.withPlacementId(...)
.build();
// Check if banner is adaptive
if (adaptiveSize.isAdaptive()) {
// Handle responsive rendering
}
```
}>
```kotlin
// Adaptive banner with width 350 and max height 100
val adaptiveSize = BannerAdSize.adaptive(350, 100)
val config = AdPlacementConfig.bannerBuilder(adaptiveSize)
.withPlacementId(...)
.build()
// Check if banner is adaptive
if (adaptiveSize.isAdaptive) {
// Handle responsive rendering
}
```
:::info Calculating Adaptive Height
Use `BannerAdSize.getMaxAdaptiveHeight(width)` to get the maximum expected banner height for a given width. Both parameter and return value are in density-independent pixels (dp).
:::
}>
```java
// Get screen width in dp
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int screenWidthDp = (int) (displayMetrics.widthPixels / displayMetrics.density);
// Calculate maximum adaptive height for screen width
int maxHeightDp = BannerAdSize.getMaxAdaptiveHeight(screenWidthDp);
// Create adaptive banner with calculated dimensions
BannerAdSize adaptiveSize = BannerAdSize.adaptive(screenWidthDp, maxHeightDp);
```
}>
```kotlin
// Get screen width in dp
val displayMetrics = resources.displayMetrics
val screenWidthDp = (displayMetrics.widthPixels / displayMetrics.density).toInt()
// Calculate maximum adaptive height for screen width
val maxHeightDp = BannerAdSize.getMaxAdaptiveHeight(screenWidthDp)
// Create adaptive banner with calculated dimensions
val adaptiveSize = BannerAdSize.adaptive(screenWidthDp, maxHeightDp)
```
### General Request
Set the `BannerRequest.AdRequestListener` instance to the`BannerRequest.Builder` instance.
}>
```java
bannerRequestBuilder.setListener(new BannerRequest.AdRequestListener() {
@Override
public void onRequestSuccess(@NonNull BannerRequest request,
@NonNull AuctionResult auctionResult) {
// Called when BannerRequest was requested successfully
}
@Override
public void onRequestFailed(@NonNull BannerRequest request,
@NonNull BMError error) {
// Called when BannerRequest request failed
}
@Override
public void onRequestExpired(@NonNull BannerRequest request) {
// Called when BannerRequest expired
}
});
```
}>
```kotlin
bannerRequestBuilder.setListener(object : BannerRequest.AdRequestListener {
override fun onRequestSuccess(request: BannerRequest,
auctionResult: AuctionResult) {
// Called when BannerRequest was requested successfully
}
override fun onRequestFailed(request: BannerRequest,
error: BMError) {
// Called when BannerRequest request failed
}
override fun onRequestExpired(request: BannerRequest) {
// Called when BannerRequest expired
}
})
```
:::note
`AdRequestListener` callbacks are delivered on the background thread, not the main one.
:::
When all the necessary parameters are set, call `build` on the `BannerRequest.Builder` instance:
}>
```java
BannerRequest bannerRequest = bannerRequestBuilder.build();
```
}>
```kotlin
val bannerRequest = bannerRequestBuilder.build()
```
:::warning Keep Ad Request
You need to keep reference to `BannerRequest` before calling `BannerRequest#request`, otherwise, it is possible it will be cleared by Garbage Collector and callbacks won’t be triggered.
:::
### Client Bidding Request
#### Bid Token
With S2S integration, you will need a `BidToken` that you need to transfer in the request.
Define `AdPlacementConfig`:
}>
```java
AdPlacementConfig adPlacementConfig = AdPlacementConfig.bannerBuilder()
.withPlacementId(...) // Set placement id
.build();
```
}>
```kotlin
val adPlacementConfig = AdPlacementConfig.bannerBuilder()
.withPlacementId(...) // Set placement id
.build()
```
To get a `BidToken`, you can use one of 2 methods:
}>
```java
// Must be run on background thread
String bidToken = BidMachine.getBidToken(@NonNull Context, @NonNull AdPlacementConfig);
```
}>
```kotlin
// Must be run on background thread
val bidToken = BidMachine.getBidToken(Context, AdPlacementConfig)
```
or
}>
```java
BidMachine.getBidToken(@NonNull Context, @NonNull AdPlacementConfig, new BidTokenCallback() {
@Override
public void onCollected(@NonNull String bidToken) {
// The BidToken will be returned on a background thread
}
});
```
}>
```kotlin
BidMachine.getBidToken(Context, AdPlacementConfig) { bidToken ->
// The BidToken will be returned on a background thread
}
```
#### Bid Payload
After completing the server-side auction, you will receive a Base64-encoded payload string, which must be passed as a parameter to the `BannerRequest.Builder`:
}>
```java
bannerRequestBuilder.setBidPayload(@Nullable String);
```
}>
```kotlin
bannerRequestBuilder.setBidPayload(String?)
```
When all the necessary parameters are set, call `build` on the `BannerRequest.Builder` instance:
}>
```java
BannerRequest bannerRequest = bannerRequestBuilder.build();
```
}>
```kotlin
val bannerRequest = bannerRequestBuilder.build()
```
:::warning Keep Ad Request
You need to keep reference to `BannerRequest` before calling `BannerRequest#request`, otherwise, it is possible it will be cleared by Garbage Collector and callbacks won’t be triggered.
:::
## Ad Display
### Prepare the Ad Request object
When you need to request an ad and get an [`AuctionResult`](/sdk/general/android/advanced#auction-info), call `request` on the `BannerRequest` instance.
}>
```java
bannerRequest.request(...);
```
}>
```kotlin
bannerRequest.request(...)
```
:::note
If you have an in-house meditation and you decide that an advertisement from BidMachine will be shown - call `bannerRequest.notifyMediationWin`, if BidMachine loses the mediation - call `bannerRequest.notifyMediationLoss`
:::
Destroy the `BannerRequest` instance if you don't need it anymore.
}>
```java
bannerRequest.destroy();
```
}>
```kotlin
bannerRequest.destroy()
```
:::warning
Don't destroy the `BannerRequest` instance, if it will be used for load the `BannerView` instance or if the `BannerView` instance loaded with the `BannerRequest` instance has not been shown yet.
Otherwise, ad will not work correctly, which can affect a lower display rate, fill rate, rendering errors, and as a result - lower revenue.
:::
### Define Ad Listener
Before executing `load` on the `BannerView` instance, set up the `BannerListener` instance:
}>
```java
BannerView bannerView = new BannerView(...);
bannerView.setListener(new BannerListener() {
@Override
public void onAdLoaded(@NonNull BannerView ad) {
// Called when Ad was loaded and ready to be displayed
}
@Override
public void onAdLoadFailed(@NonNull BannerView ad,
@NonNull BMError error) {
// Called when Ad failed to load
}
@Override
public void onAdImpression(@NonNull BannerView ad) {
// Called when Ad Impression has been tracked
}
@Override
public void onAdShowFailed(@NonNull BannerView ad,
@NonNull BMError error) {
// Called when Ad show failed
}
@Override
public void onAdClicked(@NonNull BannerView ad) {
// Called when Ad has been clicked
}
@Override
public void onAdExpired(@NonNull BannerView ad) {
// Called when Ad expired
}
});
bannerView.load(bannerRequest);
```
}>
```kotlin
val bannerView = BannerView(...)
bannerView.setListener(object : BannerListener {
override fun onAdLoaded(ad: BannerView) {
// Called when Ad was loaded and ready to be displayed
}
override fun onAdLoadFailed(ad: BannerView,
error: BMError) {
// Called when Ad failed to load
}
override fun onAdImpression(ad: BannerView) {
// Called when Ad Impression has been tracked
}
override fun onAdShowFailed(ad: BannerView,
error: BMError) {
// Called when Ad show failed
}
override fun onAdClicked(ad: BannerView) {
// Called when Ad has been clicked
}
override fun onAdExpired(ad: BannerView) {
// Called when Ad expired
}
})
bannerView.load(bannerRequest)
```
#### Get loaded ad size
`BannerView.adSize` returns the `BannerAdSize` received from the `AdResponse`. Read it in `onAdLoaded` to access the actual width and height of the creative:
}>
```java
@Override
public void onAdLoaded(@NonNull BannerView ad) {
BannerAdSize loadedSize = ad.getAdSize();
int width = loadedSize.getWidth();
int height = loadedSize.getHeight();
}
```
}>
```kotlin
override fun onAdLoaded(ad: BannerView) {
val loadedSize = ad.adSize
val width = loadedSize.width
val height = loadedSize.height
}
```
### Loading and presenting banner ads
Make sure that the `BannerRequest` instance has `AuctionResult`. It means the ads have been requested successfully.
}>
```java
bannerRequest.getAuctionResult() != null
```
}>
```kotlin
bannerRequest.auctionResult != null
```
Use `onAdLoaded` callback to determine the possibility of displaying
Before displaying, check if the `BannerView` instance can be displayed:
}>
```java
bannerView.canShow();
```
}>
```kotlin
bannerView.canShow()
```
To display the `BannerView` instance, you just need to add it to the layout.
}>
```java
viewGroup.removeAllViews();
viewGroup.addView(bannerView);
```
}>
```kotlin
viewGroup.removeAllViews()
viewGroup.addView(bannerView)
```
After ad was successful shown and no longer needed, it can be destroyed.
}>
```java
bannerView.destroy();
```
}>
```kotlin
bannerView.destroy()
```
:::info
You can find code examples written in Java and Kotlin: [Github Banner](https://github.com/bidmachine/BidMachine-Android-Examples/tree/master/bidmachine-banner)
:::
---
## Changelog(Android)
## Version 3.8.0 (August 25, 2026)
**Features**:
* Added `Picture-in-Picture` (`PiP`) support
* Improved audio handling for video ads
**Bug fixes**:
* Added protection against non-closing fullscreen ads
* Improved `GDPR` consent handling
* Fixed rare `ANR` when playing videos
* Improved `OM SDK` compatibility
## Version 3.7.1 (May 29, 2026)
**Bug fixes**:
* Improved work with `UserAgent`
* Stability improvements
## Version 3.7.0 (May 11, 2026)
**Features**:
* Updated `OM SDK` to 1.6.3
* Added disclaimer view support for native ads
* Added `CTV` device type support
* Deprecated public API methods:
```
BidMachine.setUSPrivacyString(String)
BidMachine.setConsentConfig(Boolean, String)
```
* Added public API methods:
```
BidMachine.setNonPersonalized(Boolean?)
BidMachine.setConsentStatus(Boolean)
```
**Bug fixes**:
* Fixed `NPE` in `dispatchDetachedFromWindow`
* Fixed crash in `BidMachineAd`
## Version 3.6.1 (March 23, 2026)
**Bug fixes**:
* Stability improvements
## Version 3.6.0 (March 11, 2026)
**Features**:
* Added viewability tracker for support `IAB` `MRC`
* Updated `OM SDK` to 1.6.1
* Improved `BidMachineInitProvider` performance
* Mute `WebView` audio via `androidx.webkit`
**Bug fixes**:
* Fixed rewarded video skip via app backgrounding (`singleTask`)
* Fixed `OM SDK` 1.6.1 r8 rules
* Fixed `ANR` with `WebChromeClient#getVisitedHistory`
## Version 3.5.1 (December 11, 2025)
**Features**:
- Added `BannerView.adSize` that returns `BannerAdSize` received from the `AdResponse`
- Added `BannerAdSize.getMaxAdaptiveHeight(width)` that returns maximum expected banner height for a given width
**Bug fixes:**
- Fixed banner expand issues
- Fixed `OMSDK` overlapping issues
## Version 3.5.0 (October 21, 2025)
:::warning Deprecated
`BannerSize` and `AdsFormat` enums are deprecated. Use `BannerAdSize` and `AdFormat` classes instead.
The following public API methods are deprecated:
```java
BannerRequest.Builder() // no-arg constructor
InterstitialRequest.Builder() // no-arg constructor
RewardedRequest.Builder() // no-arg constructor
NativeRequest.Builder() // no-arg constructor
BannerRequest.Builder#setSize(BannerSize)
BannerRequest#getSize()
InterstitialRequest.Builder#setAdContentType(AdContentType)
RewardedRequest.Builder#setAdContentType(AdContentType)
NativeRequest.Builder#setMediaAssetTypes(MediaAssetType...)
RequestBuilder#setPlacementId(String)
RequestBuilder#setCustomParams(CustomParams)
AdRequestParameters#getAdsFormat()
BannerAdRequestParameters#getBannerSize()
```
:::
**Features**:
- Updated public API:
- Added `AdFormat` sealed class for type-safe ad formats
- Added `AdPlacementConfig` builder methods:
```
AdPlacementConfig.bannerBuilder(BannerAdSize)
AdPlacementConfig.interstitialBuilder(AdContentType)
AdPlacementConfig.rewardedBuilder(AdContentType)
AdPlacementConfig.nativeBuilder(List)
```
- Added new request builder constructors:
```
BannerRequest.Builder(AdPlacementConfig)
InterstitialRequest.Builder(AdPlacementConfig)
RewardedRequest.Builder(AdPlacementConfig)
NativeRequest.Builder(AdPlacementConfig)
```
- Added adaptive banner support:
- New `BannerAdSize` class:
```
BannerAdSize.adaptive(width, maxHeight)
BannerAdSize.isAdaptive()
```
- Added API method:
```
BannerRequest#getBannerAdSize()
```
- Reworked asset caching logic for improved storage efficiency and faster ad caching
- Added support for inline installs on Android
- Added support for expandable MRAID ads
## Version 3.4.0 (August 7, 2025)
**Features**:
- Updated `OM SDK` to `1.5.5`
- Reduced SDK size in release builds by **15%**
- Deprecated `SessionAdParams`
- Deprecated public API methods:
```
AdRequestParameters#getSessionAdParams()
RequestBuilder#setSessionAdParams(sessionAdParams)
```
**Bug fixes:**
- Fixed `overrideActivityTransition` crash
- Fixed animation glitches
## Version 3.3.0 (May 26, 2025)
**Features**:
- Added `AdPlacementConfig`
- Added public API methods:
```
BidMachine.getBidToken(context, adPlacementConfig)
BidMachine.getBidToken(context, adPlacementConfig, callback)
```
- Removed public API methods:
```
BidMachine.getBidToken(context)
BidMachine.getBidToken(context, callback)
```
- Deprecated public API methods:
```
BidMachine.getBidToken(context, adsFormat)
BidMachine.getBidToken(context, adsFormat, callback)
```
- Changed to `@NonNull AdsFormat` in deprecated `getBidToken` methods:
```
BidMachine.getBidToken(context, adsFormat)
BidMachine.getBidToken(context, adsFormat, callback)
```
- `BidMachineInitProvider` performance improvements
## Version 3.2.1 (March 21, 2025)
**Features**:
- Removed `mraid.resize` and `mraid.expand` support
- Updated `OM SDK` to 1.5.4
- Restricted ad ids for `COPPA` traffic
**Bug fixes**:
- Fixed `BidMachineInitProvider` ANR
- Fixed `User-Agent` related ANR
## Version 3.2.0 (February 12, 2025)
**Features**:
- Added support for `ERID` requirements
- Added `Deep Links` support
- Added `User-Agent` to trackers
- Removed image aspect ratio checker from `Native Ad`
- Improved Referrer HTTP header field for `MRAID` ad
**Bug fixes**:
- Fixed `SessionManager` crash
- Fixed possible loss of networks during initialization
## Version 3.1.1 (November 19, 2024)
**Features**:
- Rollback compatibility with Gradle 7.2+ and AGP 7.1+
- Extend MRAID features support
**Bug fixes**:
- Fix `InstallReferrer` ANR
- Internal changes and stability improvements
## Version 3.1.0 (October 30, 2024)
**Features**:
- Internal changes and stability improvements
- Increased target API version to 35
- Updated `OM SDK` to 1.5.2
- Updated r8 rules
- Locked all dependencies versions
- Increased min Gradle version to 8.0
- Increased min Android Gradle Plugin version to 8.0.2
## Version 3.0.1 (September 12, 2024)
**Features**:
- Get rid of orientation in ad unit
- All views in native ads are clickable by default if no list is passed explicitly
## Version 3.0.0 (July 23, 2024)
> 🚧 Increased `minSdk` to 21 (5.0, Lollipop)
**Features**:
- Removed deprecated `RichMedia` ad type
- Deprecated `SessionPlacementData`
- Deprecated `getBidToken` methods without `AdsFormat`:
```
BidMachine.getBidToken(context)
BidMachine.getBidToken(context, callback)
```
- Updated `OM SDK` version to 1.5.0
- Added API method to get extras parameters:
```
BidMachine.getExtrasParam(context, key)
```
**Bug fixes**:
- Fixed ANR `io.bidmachine.core.Logger.log`
- Fixed `IAB` StackOverflowError when calling `Utils.findEndpoint`
## Version 2.7.0 (May 8, 2024)
**Features**:
- Added `GAM` dynamic version range support from 21.0.0 to 23.0.0
**Bug fixes**:
- Fixed `ClassCastException` with `ExoPlayer`
## Version 2.6.0 (April 5, 2024)
**Features**:
- Increased target API version to 34
- Updated `OM SDK` version to 1.4.12. Passed certification by `OM SDK`.
**Bug fixes**:
- Fixed ANR `Utils.getCacheDir`
- Fixed ANR `UserAgentProvider`
## Version 2.5.2 (March 7, 2024)
**Features**:
- Small internal dependency improvements. Excluded Multidex.
## Version 2.5.1 (March 1, 2024)
**Features**:
- Deprecated `RichMedia` ad type
- Improved processing `WebViewClient#onRenderProcessGone` (fix for possible `WebView` crashes)
## Version 2.5.0 (February 16, 2024)
**Features**:
- Improvements with internal modules
- Minor optimisation and fixes
- Optimised token fetch mechanism
## Version 2.4.2 (January 26, 2024)
**Features**:
- Internal improvements
## Version 2.4.1 (January 4, 2024)
**Features**:
- Minor improvements for enhanced internal functionality
## Version 2.4.0 (November 9, 2023)
**Features**:
- Added GPP Support
- Improved integration with Google
**Bug fixes**:
- Fixed `Context` memory leak
- Fixed `OnClose` callback
## Version 2.3.4 (November 9, 2023)
**Features**:
- Improved visibility tracking logs
**Bug fixes**:
- Fixed impression tracking with some networks
## Version 2.3.3 (September 4, 2023)
**Features**:
- Improved integration with Google.
- Improved internal tracking logic.
- Improved Native Ads tracking.
## Version 2.3.2 (August 2, 2023)
**Features**:
- Improved object cleanup during `NativeAdObject#unregisterView`
## Version 2.3.1 (July 21, 2023)
**Features**:
- SDK improvement
- Added `onAdShowFailed` callback for Banner/Mrec, Native, RichMedia ad types
## Version 2.2.0 (May 15, 2023)
**Features**:
- Updated the logic for working with `BidToken`
- Added API methods:
```
BidMachine.getBidToken(context, adsFormat)
BidMachine.getBidToken(context, adsFormat, callback)
```
**Bugfixes**:
- Moved `UserAgent` initialization from `preInitialize` to `initialize`
## Version 2.1.13 (April 13, 2023)
**Features**:
- SDK improvement
## Version 2.1.12 (March 24, 2023)
**Features**:
- SDK improvement
## Version 2.1.11 (March 14, 2023)
**Features**:
- Updated SDK events
## Version 2.1.10 (March 3, 2023)
**Features**:
- SDK improvement
## Version 2.1.9 (February 23, 2023)
**Features**:
- Improved `Utils.onBackgroundThread`
## Version 2.1.8 (February 15, 2023)
**Features**:
- SDK improvement
- Increased target API version to 33
- Added more safety for `BidMachineImpl.preInitialize`
- Added more information in error events
- Updated tracking event logic
**Bugfixes**:
- Fixed `OutOfMemory` crashes in `NetworkRequest#request`
- Fixed `NullPointerException` crashes in `AdRequest#destroy`
## Version 2.1.7 (January 26, 2023)
**Bugfixes**:
- Fixed `ConcurrentModificationException` crashes in `AdProcessCallbackComposite.executeOnCallback`
## Version 2.1.6 (January 25, 2023)
**Bugfixes**:
- Fixed `ConcurrentModificationException` crashes in `AdProcessCallbackComposite.executeOnCallback`
- Fixed `OutOfMemory` crashes in `NetworkLoadTask#execute`
- Fixed `IllegalStateException` crashes in `MediaView#tryPlayVideo`
## Version 2.1.5 (November 16, 2022)
**Features**:
- SDK improvement
## Version 2.1.4 (November 9, 2022)
**Features**:
- SDK improvement
## Version 2.1.3 (November 8, 2022)
**Features**:
- SDK improvement
## Version 2.1.2 (November 7, 2022)
**Features**:
- Updated analytics
## Version 2.1.1 (October 22, 2022)
**Bug fixes**:
- Fixed `ConcurrentModificationException` crashes in `AdResponse`
## Version 2.1.0 (September 29, 2022)
**Features**:
- SDK improvement
## Version 2.0.0 (September 5, 2022)
**Features**:
- SDK improvement
- Added Java 8
- Removed `AdListener#onAdShown`, use `AdListener#onAdImpression` instead
## Version 1.9.10 (August 16, 2022)
**Features**:
- SDK improvement
## Version 1.9.9 (August 8, 2022)
**Features**:
- SDK improvement
## Version 1.9.8 (August 1, 2022)
**Features**:
- Updated IAB library to 1.0.0
## Version 1.9.7 (July 14, 2022)
**Features**:
- Deprecated `AdListener#onAdShown`, use `AdListener#onAdImpression` instead
## Version 1.9.6 (June 30, 2022)
**Features**:
- SDK improvement
## Version 1.9.5 (June 21, 2022)
**Features**:
- SDK improvement
## Version 1.9.4 (May 30, 2022)
**Features**:
- SDK improvement
## Version 1.9.3 (March 31, 2022)
**Features**:
- SDK improvement
## Version 1.9.2 (March 16, 2022)
**Features**:
- SDK improvement
- Increased minimum API version to 16
- Increased target API version to 31
## Version 1.9.1 (February 11, 2022)
**Features**:
- Added API method `AdRequest.Builder#setCustomParams` to set custom parameters
## Version 1.9.0 (February 01, 2022)
**Features**:
- SDK improvement
- Added API method `BidMachine.getBidToken` to get BidToken for S2S integration
## Version 1.8.3 (December 29, 2021)
**Features**:
- SDK improvement
## Version 1.8.2 (December 23, 2021)
**Features**:
- SDK improvement
## Version 1.8.1 (November 26, 2021)
**Features**:
- SDK improvement
## Version 1.8.0 (October 26, 2021)
**Features**:
- Added `RichMediaView` to display video ads into the view
## Version 1.7.7 (October 21, 2021)
**Features**:
- SDK improvement
- Added API method `AdRequest#notifyMediationLoss` with WinnerNetworkName and WinnerNetworkPrice parameters to notify BidMachine of loss if you use BidMachine like in-house mediation
- Removed `AuctionResult#getSeat`
## Version 1.7.6 (July 21, 2021)
**Features**:
- SDK improvement
## Version 1.7.5 (June 30, 2021)
**Features**:
- SDK improvement
## Version 1.7.4 (May 31, 2021)
**Features**:
- SDK improvement
- Added API method `AdRequest.Builder#setPlacementId` to set placement id
- Deprecated `AuctionResult#getSeat`
## Version 1.7.3 (May 18, 2021)
**Features**:
- SDK improvement
- Added `TargetingParams#setExternalUserIds` to pass external user ids
- Removed `AdRequest.Builder#disableHeaderBidding` and `AdRequest.Builder#enableHeaderBidding`
- Removed client-side price rounding. At the same time, some deprecated methods were removed that were responsible for the price rounding from `BidMachineFetcher`
## Version 1.7.2 (April 20, 2021)
**Features**:
- SDK improvement
- Added API method `AdRequest.Builder#setBidPayload` to set BidPayload
- Added support for OMSDK version 1.3.15
## Version 1.7.1 (March 30, 2021)
**Features**:
- SDK improvement
- Added API method `AdRequest#destroy` to destroy AdRequest
- Deprecated client-side rounding, use server side rounding
- Deprecated 3rd party helpers, use adapter helpers
## Version 1.6.4 (February 12, 2021)
**Features**:
- Improved visibility tracker
## Version 1.6.3 (January 18, 2021)
**Features**:
- Banner improvement
## Version 1.6.2 (December 17, 2020)
**Features**:
- Added support TCF 2.0 - `IABTCF_TCString` and `IABTCF_gdprApplies`
## Version 1.6.1 (November 3, 2020)
**Features**:
- SDK improvement
## Version 1.6.0 (September 11, 2020)
**Features**:
- SDK improvement
- Added API method `BidMachine.setUSPrivacyString` to set US privacy string
- Added API method `AdRequest.Builder#setNetworks` to set certain networks for AdRequest
- Added API method `AdRequest.Builder#setSessionAdParams` to set additional session parameters for AdRequest
- Updated AdColony adapter version to 1.6.0.5.
- Updated Amazon adapter version to 1.6.0.3.
- Updated Facebook adapter version to 1.6.0.4.
- Updated MyTarget adapter version to 1.6.0.3.
- Updated Tapjoy adapter version to 1.6.0.4.
## Version 1.5.2 (August 3, 2020)
**Features**:
- SDK improvement
- Updated AdColony adapter version to 1.5.2.4. More info [here](https://github.com/bidmachine/BidMachine-Android-SDK/blob/master/adapters/adcolony/CHANGELOG.md)
- Updated Criteo adapter version to 1.5.2.4. More info [here](https://github.com/bidmachine/BidMachine-Android-SDK/blob/master/adapters/criteo/CHANGELOG.md)
## Version 1.5.1 (July 15, 2020)
**Features**:
- Native ad improvement
## Version 1.5.0 (July 10, 2020)
**Features**:
- SDK improvement
- Combining BidMachineFetcher and BidMachineHelper. Use BidMachineFetcher instead BidMachineHelper
- Added API method `AdRequest.Builder#setLoadingTimeOut` to set loading timeout for AdRequest
- Added API method `AdRequest#notifyMediationWin` and `AdRequest#notifyMediationLoss` to notify BidMachine of win/loss if you use BidMachine like in-house mediation
## Version 1.4.4 (May 22, 2020)
**Features**:
- Updated Amazon version to 8.3.0
- Updated Criteo version to 3.5.0
## Version 1.4.3 (April 9, 2020)
**Features**:
- Added support CCPA based on IAB. More info [here](https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/master/CCPA/Version%201.0/USP%20API.md)
- Updated AdColony version to 4.1.0
- Updated Facebook version to 5.7.1
- Updated Tapjoy version to 12.4.2
## Version 1.4.1 (January 21, 2020)
**Features**:
- Added API method `BidMachine.setPublisher` to set publisher information
- Added API methods `Builder#disableHeaderBidding` and `Builder#enableHeaderBidding` to AdRequest to disable/enable header bidding on server side
## Version 1.4.0 (November 28, 2019)
**Features**:
- Added Native Ad type
## Version 1.3.3 (September 20, 2019)
**Features**:
- Added Amazon network adapter for Header-Bidding
- Added Criteo network adapter for Header-Bidding
## Version 1.3.2 (September 12, 2019)
**Features**:
- Update compatibility with Google's Protobuf libraries
## Version 1.3.1 (September 4, 2019)
**Features**:
- Added Mintegral network adapter for Header-Bidding
- Update proguard rules
## Version 1.3.0 (August 14, 2019)
**Features**:
- Support of 3d party Ad networks adapters for Header-Bidding that work with BidMachine via SDK
- Possibility to change endpoint
- Support of GDPR settings exchange with SharedPreferences (you can found more info [here](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/Mobile%20In-App%20Consent%20APIs%20v1.0%20Final.md#how-do-third-party-sdks-vendors-access-the-consent-information-))
---
## Interstitial Ads
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
## Ad Request
### Placement
Create placement configuration using `AdPlacementConfig.interstitialBuilder()` with `AdContentType`, placement id and other parameters.
}>
```java
AdPlacementConfig config = AdPlacementConfig.interstitialBuilder()
.withPlacementId(...) // Set placement id
.withCustomParams(...) // Set custom parameters
.build();
InterstitialRequest.Builder interstitialRequestBuilder = new InterstitialRequest.Builder(config)
.setTargetingParams(...) // Set TargatingParams instance
.setPriceFloorParams(...) // Set price floor parameters
.setLoadingTimeOut(...) // Set loading timeout in milliseconds
```
}>
```kotlin
val config = AdPlacementConfig.interstitialBuilder()
.withPlacementId(...) // Set placement id
.withCustomParams(...) // Set custom parameters
.build()
val interstitialRequestBuilder = InterstitialRequest.Builder(config)
.setTargetingParams(...) // Set TargatingParams instance
.setPriceFloorParams(...) // Set price floor parameters
.setLoadingTimeOut(...) // Set loading timeout in milliseconds
```
#### AdContentType
| Type | Description |
| :------------------- | :------------------------------------------------------ |
| `AdContentType.All` | Flag to request both **Video** and **Static** ad content types. |
| `AdContentType.Static` | Flag to request **Static** ad content type only. |
| `AdContentType.Video` | Flag to request **Video** ad content type only. |
:::info
By default `AdContentType` is `AdContentType.All`
:::
### General Request
Set the `InterstitialRequest.AdRequestListener` instance to the `InterstitialRequest.Builder` instance.
}>
```java
interstitialRequestBuilder.setListener(new InterstitialRequest.AdRequestListener() {
@Override
public void onRequestSuccess(@NonNull InterstitialRequest request,
@NonNull AuctionResult auctionResult) {
// Called when InterstitialRequest was requested successfully
}
@Override
public void onRequestFailed(@NonNull InterstitialRequest request,
@NonNull BMError error) {
// Called when InterstitialRequest request failed
}
@Override
public void onRequestExpired(@NonNull InterstitialRequest request) {
// Called when InterstitialRequest expired
}
});
```
}>
```kotlin
interstitialRequestBuilder.setListener(object : InterstitialRequest.AdRequestListener {
override fun onRequestSuccess(request: InterstitialRequest,
auctionResult: AuctionResult) {
// Called when InterstitialRequest was requested successfully
}
override fun onRequestFailed(request: InterstitialRequest,
error: BMError) {
// Called when InterstitialRequest request failed
}
override fun onRequestExpired(request: InterstitialRequest) {
// Called when InterstitialRequest expired
}
})
```
:::note
`AdRequestListener` callbacks run on a background thread, not on the main thread.
:::
When all the necessary parameters are set, call `build` on the `InterstitialRequest.Builder` instance:
}>
```java
InterstitialRequest interstitialRequest = interstitialRequestBuilder.build();
```
}>
```kotlin
val interstitialRequest = interstitialRequestBuilder.build()
```
:::caution Keep ad request
You need to keep reference to `InterstitialRequest` before calling `InterstitialRequest.request`, otherwise, it is possible it will be cleared by Garbage Collector and callbacks won’t be triggered.
:::
### Client Bidding Request
#### Bid Token
With S2S integration, you will need a `BidToken` that you need to transfer in the request.
Define `AdPlacementConfig`:
}>
```java
AdPlacementConfig adPlacementConfig = AdPlacementConfig.interstitialBuilder()
.withPlacementId(...) // Set placement id
.build();
```
}>
```kotlin
val adPlacementConfig = AdPlacementConfig.interstitialBuilder()
.withPlacementId(...) // Set placement id
.build()
```
To get a `BidToken`, you can use one of 2 methods:
}>
```java
// Must be run on background thread
String bidToken = BidMachine.getBidToken(@NonNull Context, @NonNull AdPlacementConfig);
```
}>
```kotlin
// Must be run on background thread
val bidToken = BidMachine.getBidToken(Context, AdPlacementConfig)
```
or
}>
```java
BidMachine.getBidToken(@NonNull Context, @NonNull AdPlacementConfig, new BidTokenCallback() {
@Override
public void onCollected(@NonNull String bidToken) {
// The BidToken will be returned on a background thread
}
});
```
}>
```kotlin
BidMachine.getBidToken(Context, AdPlacementConfig) { bidToken ->
// The BidToken will be returned on a background thread
}
```
#### Bid Payload
After completing the server-side auction, you will receive a Base64-encoded payload string, which must be passed as a parameter to the `InterstitialRequest.Builder`:
}>
```java
interstitialRequestBuilder.setBidPayload(@Nullable String);
```
}>
```kotlin
interstitialRequestBuilder.setBidPayload(String?)
```
When all the necessary parameters are set, call `build` on the `InterstitialRequest.Builder` instance:
}>
```java
InterstitialRequest interstitialRequest = interstitialRequestBuilder.build();
```
}>
```kotlin
val interstitialRequest = interstitialRequestBuilder.build()
```
:::caution Keep ad request
You need to keep reference to `InterstitialRequest` before calling `InterstitialRequest.request`, otherwise, it is possible it will be cleared by Garbage Collector and callbacks won’t be triggered.
:::
## Ad Display
### Prepare the Ad Request object
When you need to request an ad and get an [`AuctionResult`](/sdk/general/android/advanced#auction-info), call `request` on the `InterstitialRequest` instance.
}>
```java
interstitialRequest.request(...);
```
}>
```kotlin
interstitialRequest.request(...)
```
:::info
When you made an in-house meditation and you decided that an advertisement from BidMachine will be shown - call `interstitialRequest.notifyMediationWin`, if BidMachine lost in mediation - call `interstitialRequest.notifyMediationLoss`
:::
Destroy the `InterstitialRequest` instance if you don't need it anymore.
}>
```java
interstitialRequest.destroy();
```
}>
```kotlin
interstitialRequest.destroy()
```
:::caution
Don't destroy the `InterstitialRequest` instance, if it will be used for load the `InterstitialAd` instance or if the `InterstitialAd` instance loaded with the `InterstitialRequest` instance has not been shown yet.
Otherwise, ad will not work correctly, which can affect a lower display rate, fill rate, rendering errors, and as a result - lower revenue.
:::
### Define Ad Listener
Before execute `load` on the `InterstitialAd` instance set the `InterstitialListener` instance:
}>
```java
InterstitialAd interstitialAd = new InterstitialAd(...);
interstitialAd.setListener(new InterstitialListener() {
@Override
public void onAdLoaded(@NonNull InterstitialAd ad) {
// Called when Ad was loaded and ready to be displayed
}
@Override
public void onAdLoadFailed(@NonNull InterstitialAd ad,
@NonNull BMError error) {
// Called when Ad failed to load
}
@Override
public void onAdImpression(@NonNull InterstitialAd ad) {
// Called when Ad Impression has been tracked
}
@Override
public void onAdShowFailed(@NonNull InterstitialAd ad,
@NonNull BMError error) {
// Called when Ad show failed
}
@Override
public void onAdClicked(@NonNull InterstitialAd ad) {
// Called when Ad has been clicked
}
@Override
public void onAdClosed(@NonNull InterstitialAd ad,
boolean finished) {
// Called when Ad was closed (e.g - user clicked the close button)
// finished indicates if the ad was finished (e.g - video playing completed)
}
@Override
public void onAdExpired(@NonNull InterstitialAd ad) {
// Called when Ad expired
}
});
interstitialAd.load(interstitialRequest);
```
}>
```kotlin
val interstitialAd = InterstitialAd(...)
interstitialAd.setListener(object : InterstitialListener {
override fun onAdLoaded(ad: InterstitialAd) {
// Called when Ad was loaded and ready to be displayed
}
override fun onAdLoadFailed(ad: InterstitialAd,
error: BMError) {
// Called when Ad failed to load
}
override fun onAdImpression(ad: InterstitialAd) {
// Called when Ad Impression has been tracked
}
override fun onAdShowFailed(ad: InterstitialAd,
error: BMError) {
// Called when Ad show failed
}
override fun onAdClicked(ad: InterstitialAd) {
// Called when Ad has been clicked
}
override fun onAdClosed(ad: InterstitialAd,
finished: Boolean) {
// Called when Ad was closed (e.g - user clicked the close button)
// finished indicates if the ad was finished (e.g - video playing completed)
}
override fun onAdExpired(ad: InterstitialAd) {
// Called when Ad expired
}
})
interstitialAd.load(interstitialRequest)
```
### Loading and presenting interstitial ads
Make sure that the `InterstitialRequest` instance have `AuctionResult`. It's mean ads requested successfully.
}>
```java
interstitialRequest.getAuctionResult() != null
```
}>
```kotlin
interstitialRequest.auctionResult != null
```
Use `onAdLoaded` callback to determine the possibility of displaying.
Before displaying, check if the `InterstitialAd` instance can be displayed:
}>
```java
interstitialAd.canShow();
```
}>
```kotlin
interstitialAd.canShow()
```
To display the `InterstitialAd` instance, you just need to execute `show`.
}>
```java
interstitialAd.show();
```
}>
```kotlin
interstitialAd.show()
```
After ad was successful shown and no longer needed, it can be destroyed.
}>
```java
interstitialAd.destroy();
```
}>
```kotlin
interstitialAd.destroy()
```
:::info
You can find code examples written in Java and Kotlin: [Github Interstitial](https://github.com/bidmachine/BidMachine-Android-Examples/tree/master/bidmachine-interstitial)
:::
---
## Native Ads
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
## Ad Request
### Placement
Create placement configuration using `AdPlacementConfig.nativeBuilder()` with `MediaAssetType` list, placement id and other parameters.
}>
```java
List mediaTypes = Arrays.asList(
MediaAssetType.Icon,
MediaAssetType.Image
);
AdPlacementConfig config = AdPlacementConfig.nativeBuilder(mediaTypes)
.withPlacementId(...) // Set placement id
.withCustomParams(...) // Set custom parameters
.build();
NativeRequest.Builder nativeRequestBuilder = new NativeRequest.Builder(config)
.setTargetingParams(...) // Set TargetingParams instance
.setPriceFloorParams(...) // Set price floor parameters
.setLoadingTimeOut(...) // Set loading timeout in milliseconds
```
}>
```kotlin
val mediaTypes = listOf(
MediaAssetType.Icon,
MediaAssetType.Image
)
val config = AdPlacementConfig.nativeBuilder(mediaTypes)
.withPlacementId(...) // Set placement id
.withCustomParams(...) // Set custom parameters
.build()
val nativeRequestBuilder = NativeRequest.Builder(config)
.setTargetingParams(...) // Set TargetingParams instance
.setPriceFloorParams(...) // Set price floor parameters
.setLoadingTimeOut(...) // Set loading timeout in milliseconds
```
#### MediaAssetType
| Type | Description |
| :------------------- | :------------------------------------------------- |
| MediaAssetType.All | Combination of Icon, Image and Video |
| MediaAssetType.Icon | Only icon assets will be downloaded and displayed |
| MediaAssetType.Image | Only image assets will be downloaded and displayed |
| MediaAssetType.Video | Only video assets will be downloaded and displayed |
You can also combine `MediaAssetType` by listing the list of required assets.
:::info
By default required assets are MediaAssetType.Icon and MediaAssetType.Image
:::
### General Request
Set the `NativeRequest.AdRequestListener` instance to the`NativeRequest.Builder` instance.
}>
```java
nativeRequestBuilder.setListener(new NativeRequest.AdRequestListener() {
@Override
public void onRequestSuccess(@NonNull NativeRequest request,
@NonNull AuctionResult auctionResult) {
// Called when NativeRequest was requested successfully
}
@Override
public void onRequestFailed(@NonNull NativeRequest request,
@NonNull BMError error) {
// Called when NativeRequest request failed
}
@Override
public void onRequestExpired(@NonNull NativeRequest request) {
// Called when NativeRequest expired
}
});
```
}>
```kotlin
nativeRequestBuilder.setListener(object : NativeRequest.AdRequestListener {
override fun onRequestSuccess(request: NativeRequest,
auctionResult: AuctionResult) {
// Called when NativeRequest was requested successfully
}
override fun onRequestFailed(request: NativeRequest,
error: BMError) {
// Called when NativeRequest request failed
}
override fun onRequestExpired(request: NativeRequest) {
// Called when NativeRequest expired
}
})
```
:::caution
`AdRequestListener` callbacks are delivered on the background thread, not the main one.
:::
When all the necessary parameters are set, call `build` on the `NativeRequest.Builder` instance:
}>
```java
NativeRequest nativeRequest = nativeRequestBuilder.build();
```
}>
```kotlin
val nativeRequest = nativeRequestBuilder.build()
```
:::caution Keep ad request
You need to keep reference to `NativeRequest` before calling `NativeRequest.request`, otherwise it is possible it will be cleared by Garbage Collector and callbacks won’t be triggered.
:::
### Client Bidding Request
#### Bid Token
With S2S integration, you will need a `BidToken` that you need to transfer in the request.
Define `AdPlacementConfig`:
}>
```java
List mediaTypes = Arrays.asList(
MediaAssetType.Icon,
MediaAssetType.Image
);
AdPlacementConfig adPlacementConfig = AdPlacementConfig.nativeBuilder(mediaTypes)
.withPlacementId(...) // Set placement id
.build();
```
}>
```kotlin
val mediaTypes = listOf(MediaAssetType.Icon, MediaAssetType.Image)
val adPlacementConfig = AdPlacementConfig.nativeBuilder(mediaTypes)
.withPlacementId(...) // Set placement id
.build()
```
To get a `BidToken`, you can use one of 2 methods:
}>
```java
// Must be run on background thread
String bidToken = BidMachine.getBidToken(@NonNull Context, @NonNull AdPlacementConfig);
```
}>
```kotlin
// Must be run on background thread
val bidToken = BidMachine.getBidToken(Context, AdPlacementConfig)
```
or
}>
```java
BidMachine.getBidToken(@NonNull Context, @NonNull AdPlacementConfig, new BidTokenCallback() {
@Override
public void onCollected(@NonNull String bidToken) {
// The BidToken will be returned on a background thread
}
});
```
}>
```kotlin
BidMachine.getBidToken(Context, AdPlacementConfig) { bidToken ->
// The BidToken will be returned on a background thread
}
```
#### Bid Payload
After completing the server-side auction, you will receive a Base64-encoded payload string, which must be passed as a parameter to the `NativeRequest.Builder`:
}>
```java
nativeRequestBuilder.setBidPayload(@Nullable String);
```
}>
```kotlin
nativeRequestBuilder.setBidPayload(String?)
```
When all the necessary parameters are set, call `build` on the `NativeRequest.Builder` instance:
}>
```java
NativeRequest nativeRequest = nativeRequestBuilder.build();
```
}>
```kotlin
val nativeRequest = nativeRequestBuilder.build()
```
:::caution Keep ad request
You need to keep reference to `NativeRequest` before calling `NativeRequest.request`, otherwise it is possible it will be cleared by Garbage Collector and callbacks won’t be triggered.
:::
## Ad Display
### Prepare the Ad Request object
When you need to request an ad and get an [`AuctionResult`](/sdk/general/android/advanced#auction-info), call `request` on the `NativeRequest` instance.
}>
```java
nativeRequest.request(...);
```
}>
```kotlin
nativeRequest.request(...)
```
:::info
If you have an in-house meditation and you decide that an advertisement from BidMachine will be shown - call `nativeRequest.notifyMediationWin`, if BidMachine loses the mediation - call `nativeRequest.notifyMediationLoss`
:::
Destroy the `NativeRequest` instance if you don't need it anymore.
}>
```java
nativeRequest.destroy();
```
}>
```kotlin
nativeRequest.destroy()
```
:::caution
Don't destroy the `NativeRequest` instance, if it will be used for load the `NativeAd` instance or if the `NativeAd` instance loaded with the `NativeRequest` instance has not been shown yet.
Otherwise, ad will not work correctly, which can affect a lower display rate, fill rate, rendering errors, and as a result - lower revenue.
:::
### Define Ad Listener
Before execute `load` on the `NativeAd` instance set the `NativeListener` instance:
}>
```java
NativeAd nativeAd = new NativeAd(...);
nativeAd.setListener(new NativeListener() {
@Override
public void onAdLoaded(@NonNull NativeAd ad) {
// Called when Ad was loaded and ready to be displayed
}
@Override
public void onAdLoadFailed(@NonNull NativeAd ad,
@NonNull BMError error) {
// Called when Ad failed to load
}
@Override
public void onAdImpression(@NonNull NativeAd ad) {
// Called when Ad Impression has been tracked
}
@Override
public void onAdShowFailed(@NonNull NativeAd ad,
@NonNull BMError error) {
// Called when Ad show failed
}
@Override
public void onAdClicked(@NonNull NativeAd ad) {
// Called when Ad has been clicked
}
@Override
public void onAdExpired(@NonNull NativeAd ad) {
// Called when Ad expired
}
});
nativeAd.load(nativeRequest);
```
}>
```kotlin
val nativeAd = NativeAd(...)
nativeAd.setListener(object : NativeListener {
override fun onAdLoaded(ad: NativeAd) {
// Called when Ad was loaded and ready to be displayed
}
override fun onAdLoadFailed(ad: NativeAd,
error: BMError) {
// Called when Ad failed to load
}
override fun onAdImpression(ad: NativeAd) {
// Called when Ad Impression has been tracked
}
override fun onAdShowFailed(ad: NativeAd,
error: BMError) {
// Called when Ad show failed
}
override fun onAdClicked(ad: NativeAd) {
// Called when Ad has been clicked
}
override fun onAdExpired(ad: NativeAd) {
// Called when Ad expired
}
})
nativeAd.load(nativeRequest)
```
### Define Layout
To display the `NativeAd` instance, you need:
- Create layout
- Fill `NativeAdContentLayout` by `NativeAd`
- Register `NativeAdContentLayout` for interaction
#### Create layout
Create layout which should be contain `NativeAdContentLayout` with filled attributes, which contains views IDs. These IDs are required to identify and fill views with an ad.
| Attribute | Description |
| :----------------- | :----------------------------------------------------------------- |
| titleViewId | Reference to the view that will contain the title data |
| descriptionViewId | Reference to the view that will contain the description data |
| ratingViewId | Reference to the view that will contain the rating data |
| callToActionViewId | Reference to the view that will contain the CTA data |
| iconViewId | Reference to the view that will contain the icon |
| providerViewId | Reference to the view that will contain the view that provides DAA |
| mediaViewId | Reference to the view that will contain the main image or video |
Example of `NativeAdContentLayout` layout:
```xml native_ad_content_layout.xml
```
}>
```java
NativeAdContentLayout nativeAdContentLayout = (NativeAdContentLayout) LayoutInflater.from(this)
.inflate(R.layout.include_native_ads, nativeAdParent, false);
```
}>
```kotlin
val nativeAdContentLayout = LayoutInflater.from(this)
.inflate(android.R.layout.include_native_ads, nativeAdParent, false) as NativeAdContentLayout
```
#### Fill NativeAdContentLayout by NativeAd
After creation `NativeAdContentLayout`, you need to fill the views with data from `NativeAd`.
}>
```java
nativeAdContentLayout.bind(nativeAd);
```
}>
```kotlin
nativeAdContentLayout.bind(nativeAd)
```
#### Register NativeAdContentLayout for interaction
In order to prepare the `NativeAdContentLayout` for display, you need to call `registerViewForInteraction` on it.
}>
```java
nativeAdContentLayout.registerViewForInteraction(nativeAd);
```
}>
```kotlin
nativeAdContentLayout.registerViewForInteraction(nativeAd)
```
You can unregister view if view is out of screen now.
}>
```java
nativeAdContentLayout.unregisterViewForInteraction();
```
}>
```kotlin
nativeAdContentLayout.unregisterViewForInteraction()
```
### Loading and presenting native ads
Make sure that the `NativeRequest` instance has `AuctionResult`. It means the ads have been requested successfully.
}>
```java
nativeRequest.getAuctionResult() != null
```
}>
```kotlin
nativeRequest.auctionResult != null
```
Use `onAdLoaded` callback to determine the possibility of displaying.
Before displaying, check if the `NativeAd` instance can be displayed:
}>
```java
nativeAd.canShow();
```
}>
```kotlin
nativeAd.canShow()
```
After ad was successful shown and no longer needed, it can be destroyed.
}>
```java
nativeAdContentLayout.destroy();
```
}>
```kotlin
nativeAdContentLayout.destroy()
```
:::note
You can find code examples written in Java and Kotlin: [Github Native](https://github.com/bidmachine/BidMachine-Android-Examples/tree/master/bidmachine-native)
:::
---
## Integration
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
import GroovyLabel from "@site/src/components/code-labels/groovy";
The following page describes how to integrate the BidMachine SDK into your Android app.
The latest BidMachine SDK version is `3.8.0`.
## Install the SDK
:::info Requirements
- **Minimum Android SDK version**: `21` (5.0, Lollipop)
- **Minimum Gradle version**: `8.0`
- **Minimum Android Gradle Plugin version**: `8.1.4`
:::
### Gradle
Add the following to your app-level `build.gradle` file:
```groovy title="build.gradle"
repositories {
maven {
url "https://artifactory.bidmachine.io/bidmachine"
}
}
dependencies {
implementation "io.bidmachine:ads:3.8.0"
}
```
Set Java version to 8:
```groovy title="build.gradle"
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
```
### Device Advertising ID
In mobile apps, there are no cookies. Instead, Ad Manager uses user-resettable identifiers provided by the mobile device's operating system.
Typical advertising IDs are **AdID** (Android) and **IDFA** (Apple). Mobile advertising IDs allow developers and marketers to track activity for advertising purposes. They're also used to enhance serving and targeting capabilities.
Add Play Services Ads Identifier dependency:
```groovy title="build.gradle"
implementation "com.google.android.gms:play-services-ads-identifier:18.2.0"
```
### Network Security Configuration
[Android 9.0 (API 28) blocks cleartext (non-HTTPS) traffic by default](https://developer.android.com/training/articles/security-config), which can prevent ads from being served correctly.
:::warning
Failure to comply with this configuration may result in:
- Lower display rate
- Reduced fill rate
- Rendering errors
- Lower revenue
:::
1. Add a **Network Security Configuration** file to your `AndroidManifest.xml`:
```xml title="AndroidManifest.xml"
```
2. In your `network_security_config.xml` file, add a base configuration that sets `cleartextTrafficPermitted` to `true`:
```xml title="network_security_config.xml"
```
## Initialize the SDK
Initialize the SDK and set your **Source ID**.
:::tip
To get your `SOURCE_ID`, visit [our website](https://bidmachine.io) or contact support.
:::
}>
```java
BidMachine.initialize(@NonNull Context, "");
// or with InitializationCallback
BidMachine.initialize(@NonNull Context, "", @Nullable InitializationCallback);
```
}>
```kotlin
BidMachine.initialize(Context, "")
// or with InitializationCallback
BidMachine.initialize(Context, "", InitializationCallback?)
```
---
## Data Privacy
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
BidMachine SDK provides APIs to support publisher compliance with major privacy regulations.
Publishers should set all privacy flags **before initializing the SDK** so the values are applied correctly.
Publishers are responsible for collecting consent from users and passing the appropriate signals to the SDK.
## GDPR
The EU's General Data Protection Regulation (GDPR) applies to users in the European Economic Area (EEA), UK, and Switzerland.
### Using a Consent Management Platform (recommended)
Publishers should integrate a consent management platform that complies with [IAB TCF v2](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/Consent%20string%20and%20vendor%20list%20formats%20v1.1%20Final.md).
Publishers must not load ads until the consent management platform has determined the user's consent status.
BidMachine SDK automatically reads the TCF v2 consent string set by the consent management platform.
:::note
BidMachine does not audit consent management platforms for TCF compliance or adherence to applicable privacy laws.
:::
### Manually
If publishers do not use a consent management platform, consent signals can be passed directly to the SDK.
**Subject to GDPR** — publishers use the following API to indicate whether the user is subject to GDPR:
}>
```java
BidMachine.setSubjectToGDPR(@Nullable Boolean);
```
}>
```kotlin
BidMachine.setSubjectToGDPR(Boolean?)
```
**User consent** — publishers use the following API to indicate whether the user has given consent for personalized data processing:
}>
```java
BidMachine.setConsentStatus(boolean);
```
}>
```kotlin
BidMachine.setConsentStatus(Boolean)
```
:::warning Deprecated since 3.7.0
`BidMachine.setConsentConfig` is deprecated. Publishers should use `BidMachine.setConsentStatus(bool)` instead.
:::
}>
```java
BidMachine.setConsentConfig(boolean, @Nullable String);
```
}>
```kotlin
BidMachine.setConsentConfig(Boolean, String?)
```
## CCPA
The California Consumer Privacy Act (CCPA) applies to users in California, effective July 1, 2020.
BidMachine SDK automatically reads the US Privacy String from `SharedPreferences` when it is set by the publisher's consent management platform according to the [IAB USPrivacy API spec](https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/master/CCPA/USP%20API.md#in-app-support). For more information on the string format, see the [IAB US Privacy String spec](https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/master/CCPA/US%20Privacy%20String.md).
If publishers must pass the US Privacy String manually:
:::warning Deprecated since 3.7.0
`BidMachine.setUSPrivacyString` is deprecated. The IAB US Privacy String format only covers California (CCPA) and does not extend to other US state privacy laws.
The [GPP](#gpp) framework supersedes it with a unified standard that covers all US state laws (California, Virginia, Colorado, Connecticut, and others) under a single string.
Publishers should use a GPP-compliant consent management platform or pass signals via `BidMachine.setGPP` instead.
:::
}>
```java
BidMachine.setUSPrivacyString(@Nullable String);
```
}>
```kotlin
BidMachine.setUSPrivacyString(String?)
```
## COPPA
The Children's Online Privacy Protection Act (COPPA) applies to users under 13 years old in the US.
Publishers should set this flag to `true` for apps directed at children or when they know that a specific user is under 13.
}>
```java
BidMachine.setCoppa(@Nullable Boolean);
```
}>
```kotlin
BidMachine.setCoppa(Boolean?)
```
## GPP
The Global Privacy Platform (GPP) is a unified framework for transmitting privacy, consent, and consumer-choice signals across jurisdictions. It covers US state laws (including CCPA), GDPR, and other regional regulations.
### Using a Consent Management Platform (recommended)
If the publisher's consent management platform supports the [IAB GPP spec](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform), BidMachine SDK automatically reads GPP data from `SharedPreferences`.
### Manually
To pass GPP data directly, publishers provide the GPP string and the applicable section IDs:
}>
```java
BidMachine.setGPP(@Nullable String, @Nullable List);
```
}>
```kotlin
BidMachine.setGPP(String?, List?)
```
## Non-Personalized Ads
Available since SDK `3.7.0`. Publishers use this flag to request non-personalized ads and to limit the data BidMachine collects and shares with demand partners.
This is relevant in several scenarios:
- **Age-restricted users in the US** — US state laws (CCPA/CPRA in California, and similar laws in Virginia, Colorado, Connecticut, and others) prohibit selling or sharing personal data of users under 16 without opt-in consent. For users under 13, COPPA applies stricter rules. Publishers should use this flag alongside `setCoppa` when they cannot determine the exact age but targeting must be limited.
- **Users who declined personalized advertising** — when a user opts out of personalized ads through the publisher's consent flow but is not subject to a specific regulation covered by the other APIs.
- **General opt-out** — as a catch-all to suppress targeting signals when none of the more specific privacy flags apply.
When set to `true`, BidMachine requests non-personalized ads only.
}>
```java
BidMachine.setNonPersonalized(@Nullable Boolean);
```
}>
```kotlin
BidMachine.setNonPersonalized(Boolean?)
```
---
## Rewarded Ads
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
## Ad Request
### Placement
Create placement configuration using `AdPlacementConfig.rewardedBuilder()` with `AdContentType`, placement id and other parameters.
}>
```java
AdPlacementConfig config = AdPlacementConfig.rewardedBuilder()
.withPlacementId(...) // Set placement id
.withCustomParams(...) // Set custom parameters
.build();
RewardedRequest.Builder rewardedRequestBuilder = new RewardedRequest.Builder(config)
.setTargetingParams(...) // Set TargetingParams instance
.setPriceFloorParams(...) // Set price floor parameters
.setLoadingTimeOut(...) // Set loading timeout in milliseconds
```
}>
```kotlin
val config = AdPlacementConfig.rewardedBuilder()
.withPlacementId(...) // Set placement id
.withCustomParams(...) // Set custom parameters
.build()
val rewardedRequestBuilder = RewardedRequest.Builder(config)
.setTargetingParams(...) // Set TargetingParams instance
.setPriceFloorParams(...) // Set price floor parameters
.setLoadingTimeOut(...) // Set loading timeout in milliseconds
```
### General Request
Set the `RewardedRequest.AdRequestListener` instance to the`RewardedRequest.Builder` instance.
}>
```java
rewardedRequestBuilder.setListener(new RewardedRequest.AdRequestListener() {
@Override
public void onRequestSuccess(@NonNull RewardedRequest request,
@NonNull AuctionResult auctionResult) {
// Called when RewardedRequest was requested successfully
}
@Override
public void onRequestFailed(@NonNull RewardedRequest request,
@NonNull BMError error) {
// Called when RewardedRequest request failed
}
@Override
public void onRequestExpired(@NonNull RewardedRequest request) {
// Called when RewardedRequest expired
}
});
```
}>
```kotlin
rewardedRequestBuilder.setListener(object : RewardedRequest.AdRequestListener {
override fun onRequestSuccess(request: RewardedRequest,
auctionResult: AuctionResult) {
// Called when RewardedRequest was requested successfully
}
override fun onRequestFailed(request: RewardedRequest,
error: BMError) {
// Called when RewardedRequest request failed
}
override fun onRequestExpired(request: RewardedRequest) {
// Called when RewardedRequest expired
}
})
```
:::info
`AdRequestListener` callbacks are delivered on the background thread, not the main one.
:::
When all the necessary parameters are set, call `build` on the `RewardedRequest.Builder` instance:
}>
```java
RewardedRequest rewardedRequest = rewardedRequestBuilder.build();
```
}>
```kotlin
val rewardedRequest = rewardedRequestBuilder.build()
```
:::info
You need to keep reference to `RewardedRequest` before calling `RewardedRequest#request`, otherwise, it is possible it will be cleared by Garbage Collector and callbacks won’t be triggered.
:::
### Client Bidding Request
#### Bid Token
With S2S integration, you will need a `BidToken` that you need to transfer in the request.
Define `AdPlacementConfig`:
}>
```java
AdPlacementConfig adPlacementConfig = AdPlacementConfig.rewardedBuilder()
.withPlacementId(...) // Set placement id
.build();
```
}>
```kotlin
val adPlacementConfig = AdPlacementConfig.rewardedBuilder()
.withPlacementId(...) // Set placement id
.build()
```
To get a `BidToken`, you can use one of 2 methods:
}>
```java
// Must be run on background thread
String bidToken = BidMachine.getBidToken(@NonNull Context, @NonNull AdPlacementConfig);
```
}>
```kotlin
// Must be run on background thread
val bidToken = BidMachine.getBidToken(Context, AdPlacementConfig)
```
or
}>
```java
BidMachine.getBidToken(@NonNull Context, @NonNull AdPlacementConfig, new BidTokenCallback() {
@Override
public void onCollected(@NonNull String bidToken) {
// The BidToken will be returned on a background thread
}
});
```
}>
```kotlin
BidMachine.getBidToken(Context, AdPlacementConfig) { bidToken ->
// The BidToken will be returned on a background thread
}
```
#### Bid Payload
After completing the server-side auction, you will receive a Base64-encoded payload string, which must be passed as a parameter to the `RewardedRequest.Builder`:
}>
```java
rewardedRequestBuilder.setBidPayload(@Nullable String);
```
}>
```kotlin
rewardedRequestBuilder.setBidPayload(String?)
```
When all the necessary parameters are set, call `build` on the `RewardedRequest.Builder` instance:
}>
```java
RewardedRequest rewardedRequest = rewardedRequestBuilder.build();
```
}>
```kotlin
val rewardedRequest = rewardedRequestBuilder.build()
```
:::info
You need to keep reference to `RewardedRequest` before calling `RewardedRequest#request`, otherwise, it is possible it will be cleared by Garbage Collector and callbacks won’t be triggered.
:::
## Ad Display
### Prepare the Ad Request object
When you need to request an ad and get an [`AuctionResult`](/sdk/general/android/advanced#auction-info), call `request` on the `RewardedRequest` instance.
}>
```java
rewardedRequest.request(...);
```
}>
```kotlin
rewardedRequest.request(...)
```
:::info
When you made an in-house meditation and you decided that an advertisement from BidMachine will be shown - call `rewardedRequest.notifyMediationWin`, if BidMachine lost in mediation - call `rewardedRequest.notifyMediationLoss`
:::
Destroy the `RewardedRequest` instance if you don't need it anymore.
}>
```java
rewardedRequest.destroy();
```
}>
```kotlin
rewardedRequest.destroy()
```
:::caution
Don't destroy the `RewardedRequest` instance, if it will be used for load the `RewardedAd` instance or if the `RewardedAd` instance loaded with the `RewardedRequest` instance has not been shown yet.
Otherwise, ad will not work correctly, which can affect a lower display rate, fill rate, rendering errors, and as a result - lower revenue.
:::
### Define Ad Listener
Before execute `load` on the `RewardedAd` instance set the `RewardedListener` instance:
}>
```java
RewardedAd rewardedAd = new RewardedAd(...);
rewardedAd.setListener(new RewardedListener() {
@Override
public void onAdLoaded(@NonNull RewardedAd ad) {
// Called when Ad was loaded and ready to be displayed
}
@Override
public void onAdLoadFailed(@NonNull RewardedAd ad,
@NonNull BMError error) {
// Called when Ad failed to load
}
@Override
public void onAdImpression(@NonNull RewardedAd ad) {
// Called when Ad Impression has been tracked
}
@Override
public void onAdShowFailed(@NonNull RewardedAd ad,
@NonNull BMError error) {
// Called when Ad show failed
}
@Override
public void onAdClicked(@NonNull RewardedAd ad) {
// Called when Ad has been clicked
}
@Override
public void onAdRewarded(@NonNull RewardedAd ad) {
// Called when Rewarded Ad was completed (e.g.: the video has been played to the end).
// You can use this event to reward the user
}
@Override
public void onAdClosed(@NonNull RewardedAd ad,
boolean finished) {
// Called when Ad was closed (e.g - user clicked the close button)
// finished indicates if the ad was finished (e.g - video playing completed)
}
@Override
public void onAdExpired(@NonNull RewardedAd ad) {
// Called when Ad expired
}
});
rewardedAd.load(rewardedRequest);
```
}>
```kotlin
val rewardedAd = RewardedAd(...)
rewardedAd.setListener(object : RewardedListener {
override fun onAdLoaded(ad: RewardedAd) {
// Called when Ad was loaded and ready to be displayed
}
override fun onAdLoadFailed(ad: RewardedAd,
error: BMError) {
// Called when Ad failed to load
}
override fun onAdImpression(ad: RewardedAd) {
// Called when Ad Impression has been tracked
}
override fun onAdShowFailed(ad: RewardedAd,
error: BMError) {
// Called when Ad show failed
}
override fun onAdClicked(ad: RewardedAd) {
// Called when Ad has been clicked
}
override fun onAdRewarded(ad: RewardedAd) {
// Called when Rewarded Ad was completed (e.g.: the video has been played to the end).
// You can use this event to reward the user
}
override fun onAdClosed(ad: RewardedAd,
finished: Boolean) {
// Called when Ad was closed (e.g - user clicked the close button)
// finished indicates if the ad was finished (e.g - video playing completed)
}
override fun onAdExpired(ad: RewardedAd) {
// Called when Ad expired
}
})
rewardedAd.load(rewardedRequest)
```
### Loading and presenting rewarded ads
Make sure that the `RewardedRequest` instance have `AuctionResult`. It's mean ads requested successfully.
}>
```java
rewardedRequest.getAuctionResult() != null
```
}>
```kotlin
rewardedRequest.auctionResult != null
```
Use `onAdLoaded` callback to determine the possibility of displaying
Before displaying, check if the `RewardedAd` instance can be displayed:
}>
```java
rewardedAd.canShow();
```
}>
```kotlin
rewardedAd.canShow()
```
To display the `RewardedAd` instance, you just need to execute `show`.
}>
```java
rewardedAd.show();
```
}>
```kotlin
rewardedAd.show()
```
After ad was successful shown and no longer needed, it can be destroyed.
}>
```java
rewardedAd.destroy();
```
}>
```kotlin
rewardedAd.destroy()
```
:::info
You can find code examples written in Java and Kotlin: [Github Rewarded](https://github.com/bidmachine/BidMachine-Android-Examples/tree/master/bidmachine-rewarded)
:::
---
## 3rd party SDK integration (Header-Bidding)
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
## 3rd party SDK integration (Header-Bidding)
You can find all integration code examples written in Java and Kotlin [here](https://github.com/bidmachine/BidMachine-Android-Examples/tree/master/bidmachine-header-bidding).
:::caution
All 3rd party networks should be configured and registered before SDK initialization
:::
### Amazon

:::info Supported ad types
- Banner
- Interstitial
- Rewarded
:::
Add this to Module-level `build.gradle` before dependencies:
```groovy build.gradle
repositories {
mavenCentral()
}
```
Add next dependency to you `build.gradle`:
```groovy build.gradle
dependencies {
implementation "io.bidmachine:ads.networks.amazon:3.5.0.18"
}
```
Configure network:
}>
```java
BidMachine.registerNetworks(
new AmazonConfig("YOUR_APP_KEY")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.Banner), "YOUR_SLOT_UUID")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.MediumRectangle), "YOUR_SLOT_UUID")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.Leaderboard), "YOUR_SLOT_UUID")
.withMediationConfig(new AdFormat.Interstitial(AdContentType.Static), "YOUR_SLOT_UUID")
.withMediationConfig(new AdFormat.Interstitial(AdContentType.Video), "YOUR_SLOT_UUID"));
```
}>
```kotlin
BidMachine.registerNetworks(
AmazonConfig("YOUR_APP_KEY")
.withMediationConfig(AdFormat.Banner(BannerAdSize.Banner), "YOUR_SLOT_UUID")
.withMediationConfig(AdFormat.Banner(BannerAdSize.MediumRectangle), "YOUR_SLOT_UUID")
.withMediationConfig(AdFormat.Banner(BannerAdSize.Leaderboard), "YOUR_SLOT_UUID")
.withMediationConfig(AdFormat.Interstitial(AdContentType.Static), "YOUR_SLOT_UUID")
.withMediationConfig(AdFormat.Interstitial(AdContentType.Video), "YOUR_SLOT_UUID"))
```
:::caution IAB TCFv2
Amazon supports only IAB TCFv2.
IAB TCFv1 is not supported, [see](https://ams.amazon.com/webpublisher/uam/docs/aps-mobile/gdpr).
:::
### Criteo

:::info Supported ad types
- Banner
- Interstitial
:::
Add this to Module-level `build.gradle` before dependencies:
```groovy build.gradle
repositories {
google()
mavenCentral()
}
```
Add the following dependency to you `build.gradle`:
```groovy
dependencies {
implementation "io.bidmachine:ads.networks.criteo:3.5.0.13"
}
```
Configure network:
}>
```java
BidMachine.registerNetworks(
new CriteoConfig("YOUR_PUBLISHER_ID")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.Banner), "YOUR_AD_UNIT_ID")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.MediumRectangle), "YOUR_AD_UNIT_ID")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.Leaderboard), "YOUR_AD_UNIT_ID")
.withMediationConfig(new AdFormat.Interstitial(AdContentType.Static), "YOUR_AD_UNIT_ID"));
```
}>
```kotlin
BidMachine.registerNetworks(
CriteoConfig("YOUR_PUBLISHER_ID")
.withMediationConfig(AdFormat.Banner(BannerAdSize.Banner), "YOUR_AD_UNIT_ID")
.withMediationConfig(AdFormat.Banner(BannerAdSize.MediumRectangle), "YOUR_AD_UNIT_ID")
.withMediationConfig(AdFormat.Banner(BannerAdSize.Leaderboard), "YOUR_AD_UNIT_ID")
.withMediationConfig(AdFormat.Interstitial(AdContentType.Static), "YOUR_AD_UNIT_ID"))
```
### Google AdManager

:::info Supported ad types
- Banner
- Interstitial
- Rewarded
:::
Add this to Project-level `build.gradle` before dependencies:
```groovy build.gradle
buildscript {
repositories {
google()
mavenCentral()
}
}
```
Add this to Module-level `build.gradle` before dependencies:
```groovy build.gradle
repositories {
google()
mavenCentral()
}
```
Add the following dependency to you `build.gradle`:
```groovy build.gradle
dependencies {
implementation "com.google.android.gms:play-services-ads:24.3.0"
}
```
:::info Supported versions
You can use any version from 21.0.0 to 24.3.0 for `com.google.android.gms:play-services-ads` dependency.
:::
Add `APPLICATION_ID` to `AndroidManifest.xml`:
```xml AndroidManifest.xml
```
:::info
If ANRs are observed when loading ad, then you can specify a special flag in `AndroidManifest.xml` that will move the loading of ad to the background thread.
```xml AndroidManifest.xml
```
[Optimize initialization and ad loading](https://developers.google.com/ad-manager/mobile-ads-sdk/android/optimize-initialization)
:::
### MetaAudience

:::info Supported ad types
- Banner
- Interstitial
- Rewarded
- Native (experimental)
:::
Add this to Module-level `build.gradle` before dependencies:
```groovy build.gradle
repositories {
mavenCentral()
}
```
Add the following dependency to you `build.gradle`:
```groovy build.gradle
dependencies {
implementation "io.bidmachine:ads.networks.meta_audience:3.5.0.17"
}
```
Update your `network_security_config.xml` file, add `domain-config` that sets `cleartextTrafficPermitted` to true:
```xml network_security_config.xml
127.0.0.1
```
Configure network:
}>
```java
BidMachine.registerNetworks(
new MetaAudienceConfig("YOUR_APP_ID")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.Banner), "YOUR_PLACEMENT_ID")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.MediumRectangle), "YOUR_PLACEMENT_ID")
.withMediationConfig(new AdFormat.Interstitial(AdContentType.Static), "YOUR_PLACEMENT_ID")
.withMediationConfig(new AdFormat.Rewarded(AdContentType.Video), "YOUR_PLACEMENT_ID")
.withMediationConfig(new AdFormat.Native(Arrays.asList(MediaAssetType.Icon, MediaAssetType.Image)), "YOUR_PLACEMENT_ID"));
```
}>
```kotlin
BidMachine.registerNetworks(
MetaAudienceConfig("YOUR_APP_ID")
.withMediationConfig(AdFormat.Banner(BannerAdSize.Banner), "YOUR_PLACEMENT_ID")
.withMediationConfig(AdFormat.Banner(BannerAdSize.MediumRectangle), "YOUR_PLACEMENT_ID")
.withMediationConfig(AdFormat.Interstitial(AdContentType.Static), "YOUR_PLACEMENT_ID")
.withMediationConfig(AdFormat.Rewarded(AdContentType.Video), "YOUR_PLACEMENT_ID")
.withMediationConfig(AdFormat.Native(listOf(MediaAssetType.Icon, MediaAssetType.Image)), "YOUR_PLACEMENT_ID"))
```
:::caution Native (Experimental)
MetaAudience native has two types:
- Native Banner Ads
- Native Ads
Native ads may not work correctly if MetaAudience placements were submitted that did not match the selected MediaAssetType.
For example, if you want to use **MediaAssetType.Icon**, you need to submit placements of **Native Banner Ads** type, otherwise you need to submit placements of **Native Ads** type.
:::
### Mintegral

:::info Supported ad types
- Banner
- Interstitial
- Rewarded
:::
Add the following dependency to you `build.gradle`:
```groovy build.gradle
dependencies {
implementation "io.bidmachine:ads.networks.mintegral:3.5.0.14"
}
```
Configure network:
}>
```java
BidMachine.registerNetworks(
new MintegralConfig("YOUR_APP_ID", "YOUR_APP_KEY")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.Banner), "YOUR_AD_UNIT_ID")
.withMediationConfig(new AdFormat.Interstitial(AdContentType.All), "YOUR_AD_UNIT_ID")
.withMediationConfig(new AdFormat.Rewarded(AdContentType.All), "YOUR_AD_UNIT_ID"));
```
}>
```kotlin
BidMachine.registerNetworks(
MintegralConfig("YOUR_APP_ID", "YOUR_APP_KEY")
.withMediationConfig(AdFormat.Banner(BannerAdSize.Banner), "YOUR_AD_UNIT_ID")
.withMediationConfig(AdFormat.Interstitial(AdContentType.All), "YOUR_AD_UNIT_ID")
.withMediationConfig(AdFormat.Rewarded(AdContentType.All), "YOUR_AD_UNIT_ID"))
```
### myTarget

:::info Supported ad types
- Banner
- Interstitial
- Rewarded
:::
Add the following dependency to you `build.gradle`:
```groovy build.gradle
dependencies {
implementation "io.bidmachine:ads.networks.my_target:3.5.0.19"
}
```
Configure network:
}>
```java
BidMachine.registerNetworks(
new MyTargetConfig()
.withMediationConfig(new AdFormat.Banner(BannerAdSize.Banner), "YOUR_SLOT_ID")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.Banner), "YOUR_SLOT_ID")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.MediumRectangle), "YOUR_SLOT_ID")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.Leaderboard), "YOUR_SLOT_ID")
.withMediationConfig(new AdFormat.Interstitial(AdContentType.Static), "YOUR_SLOT_ID")
.withMediationConfig(new AdFormat.Rewarded(AdContentType.Video), "YOUR_SLOT_ID"));
```
}>
```kotlin
BidMachine.registerNetworks(
MyTargetConfig()
.withMediationConfig(AdFormat.Banner(BannerAdSize.Banner), "YOUR_SLOT_ID")
.withMediationConfig(AdFormat.Banner(BannerAdSize.Banner), "YOUR_SLOT_ID")
.withMediationConfig(AdFormat.Banner(BannerAdSize.MediumRectangle), "YOUR_SLOT_ID")
.withMediationConfig(AdFormat.Banner(BannerAdSize.Leaderboard), "YOUR_SLOT_ID")
.withMediationConfig(AdFormat.Interstitial(AdContentType.Static), "YOUR_SLOT_ID")
.withMediationConfig(AdFormat.Rewarded(AdContentType.Video), "YOUR_SLOT_ID"))
```
### Pangle

:::info Supported ad types
- Banner
- Interstitial
- Rewarded
:::
Add the following dependency to you `build.gradle`:
```groovy build.gradle
dependencies {
implementation "io.bidmachine:ads.networks.pangle:3.5.0.13"
}
```
Configure network:
}>
```java
BidMachine.registerNetworks(
new PangleConfig("YOUR_APP_ID")
.withMediationConfig(new AdFormat.Banner(BannerAdSize.Banner), "YOUR_SLOT_ID")
.withMediationConfig(new AdFormat.Interstitial(AdContentType.All), "YOUR_SLOT_ID")
.withMediationConfig(new AdFormat.Rewarded(AdContentType.All), "YOUR_SLOT_ID"));
```
}>
```kotlin
BidMachine.registerNetworks(
PangleConfig("YOUR_APP_ID")
.withMediationConfig(AdFormat.Banner(BannerAdSize.Banner), "YOUR_SLOT_ID")
.withMediationConfig(AdFormat.Interstitial(AdContentType.All), "YOUR_SLOT_ID")
.withMediationConfig(AdFormat.Rewarded(AdContentType.All), "YOUR_SLOT_ID"))
```
### Vungle

:::info Supported ad types
- Banner
- Interstitial
- Rewarded
:::
Add this to Module-level `build.gradle` before dependencies:
```groovy build.gradle
repositories {
google()
mavenCentral()
}
```
Add the following dependency to you `build.gradle`:
```groovy build.gradle
dependencies {
implementation "io.bidmachine:ads.networks.vungle:3.5.0.9"
}
```
Configure network:
}>
```java
BidMachine.registerNetworks(
new VungleConfig("YOUR_APP_ID", "YOUR_PUBLISHER_ID")
.withMediationConfig(new AdFormat.Interstitial(AdContentType.Video), "YOUR_PLACEMENT_ID")
.withMediationConfig(new AdFormat.Rewarded(AdContentType.Video), "YOUR_PLACEMENT_ID"));
```
}>
```kotlin
BidMachine.registerNetworks(
VungleConfig("YOUR_APP_ID", "YOUR_PUBLISHER_ID")
.withMediationConfig(AdFormat.Interstitial(AdContentType.Video), "YOUR_PLACEMENT_ID")
.withMediationConfig(AdFormat.Rewarded(AdContentType.Video), "YOUR_PLACEMENT_ID"))
```
---
## In-House Bidder Specification
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjCLabel from "@site/src/components/code-labels/objc";
## Overview
BidMachine bidding supports [oRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) protocol to receive bids from supply partners and return bid responses. To integrate with BidMachine, the supply partner should integrate BidMachine SDK and the bid request should be compliant with Open RTB 2.5 Spec.
## Protocol
BidMachine service requires HTTP protocol and recommends TLS 1.2 or above.
## Request Regions
BidMachine servers are located in regions: US, EU, APAC. We highly recommend supply partners use the same region for RTB calls to avoid latency.
## Endpoint
- EU region: `https://api-eu.bidmachine.io/auction/prebid/${source_id}`
- US region: `https://api-us.bidmachine.io/auction/prebid/${source_id}`
- APAC region: `https://api-apac.bidmachine.io/auction/prebid/${source_id}`
## Supported Ad Formats
BidMachine only participates in mobile in-app auctions. Supported ad formats are:
- Fullscreen banner (`320x480`; `480x320`; `1024x768`; `768x1024`)
- Small banner (`320x50`; `728x90`)
- Skippable video (`320x480`; `480x320`; `1024x768`; `768x1024`)
- Rewarded video (`320x480`; `480x320`; `1024x768`; `768x1024`)
- Native Ads
## Supported Currency
USD only.
## Supported Auction Type
First-price auction Only.
## Bid Request
BidMachine server only takes one single impression in each bid request.
Key oRTB fields:
- `app.bundle` (required)
- `app.storeurl` (required)
- `app.name` (required)
- `imp.instl` (required)
- `device.os` (required)
- `tmax` (Required and recommended value >1000ms)
A full BidMachine oRTB Bid Request Specification can be checked [here](/sdk/ssp/request/specification).
:::info
1. Partners should share a bid request example that they planning to use for the integration.
2. If partners have their own bid request spec and would like BidMachine to respect, please contact your BidMachine Account Manager.
:::
## Bid Response
BidMachine's bid response adheres to the **Open RTB 2.5** protocol.
### No Bid
To communicate a no-bid response, BidMachine passes an empty response with a status code 204.
### Notifications
We require `win` and `loss` notifications with the appropriate loss codes as defined in oRTB.
oRTB `NURL` and `LURL` are provided in the bid response.
If partners have any customized auction substitution macros, please notify BidMachine to support in the notification URL.
[Response](/sdk/ssp/response/examples) and [Request](/sdk/ssp/request/examples) Examples.
---
## Data Collection Practices
The BidMachine SDK collects the following device and app parameters, subject to COPPA and GDPR restrictions as indicated.
| Parameter | COPPA Restricted | GDPR Restricted |
| ----------------------- | :--------------: | :-------------: |
| Device Type | | |
| User Agent | ✅ Do not collect | |
| Advertising ID / IDFA | ✅ Do not collect | ✅ Do not collect |
| Identifier for Vendor (IFV) | ✅ Do not collect | |
| Limit Ad Tracking | | |
| Location | ✅ Do not collect | ✅ Do not collect|
| UTC Offset | | |
| Connection Time | ✅ Do not collect | |
| MCC / MNC | ✅ Do not collect | |
| Carrier | ✅ Do not collect | |
| Display Width | | |
| Display Height | | |
| Display Pixel Ratio | | |
| Display DPI | | |
| Operating System | | |
| OS Version | | |
| Device Hardware Version | ✅ Do not collect | |
| Device Manufacturer | ✅ Do not collect | |
| Device Model | ✅ Do not collect | |
| Device Language | ✅ Do not collect | |
| App Bundle Identifier | | |
| App Version | | |
| App Name | | |
Location is collected only if the host app has obtained a location permission from the user; with a fine/precise location permission, precise coordinates are collected. The BidMachine SDK never requests location permissions itself. See the platform privacy details pages for the exact disclosure guidance: [Google Play](./android/app-privacy-details.mdx), [App Store](./ios/app-privacy-details.mdx).
---
## Advanced Settings(Ios)
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjcLabel from "@site/src/components/code-labels/objc";
## Global Settings
### Logs
BidMachine SDK provides a set of logging options to help you debug and monitor the SDK's behavior.
You can enable or disable different types of logs, such as general logs, bid logs, and event logs.
}>
```swift
BidMachineSdk.shared
.withLoggingMode(true)
.withBidLoggingMode(true)
.withEventLoggingMode(true)
```
}>
```objc
[BidMachineSdk.shared withLoggingMode:YES];
[BidMachineSdk.shared withBidLoggingMode:YES];
[BidMachineSdk.shared withEventLoggingMode:YES];
```
### Test mode
BidMachine SDK can be configured to run in test mode, which is useful for testing and debugging purposes.
}>
```swift
BidMachineSdk.shared.withTestMode(true)
```
}>
```objc
[BidMachineSdk.shared withTestMode:YES];
```
### Location
SDK can automatically track user device location to serve better ads.
SDK won't use location data unless the user explicitly enables it.
### Publisher Parameters
The publisher info is used to provide information about the publisher of the app.
This information is used for targeting and reporting purposes.
}>
```swift
BidMachineSdk.shared
.withPubId("")
.withPubName("")
.withPubDomain("")
.withPubCategories([])
```
}>
```objc
[BidMachineSdk.shared withPubId:@""];
[BidMachineSdk.shared withPubName:@""];
[BidMachineSdk.shared withPubDomain:@""];
[BidMachineSdk.shared withPubCategories:@[]];
```
| Parameter | Type | Description |
|:------------|:------------------|:---------------------|
| `id` | `String` | Publisher ID |
| `name` | `String` | Publisher name |
| `domain` | `String` | Publisher domain |
| `categories`| `Array` | Publisher categories |
### Targeting Parameters
The targeting info is used to provide information about the user and the app.
}>
```swift
BidMachineSdk.shared
.withUserId("")
.withUserGender(.male)
.withUserYOB(UInt32(1))
.withLocation(CLLocation(latitude: 1, longitude: 2))
.withCountry("")
.withCity("")
.withZip("")
.withKeywords("")
.withBlockedApps([])
.withBlockedCategories([])
.withBlockedAdvertisers([])
.withStoreURL("")
.withStoreId("")
.withStoreCategory("")
.withStoreSubCategories([])
.withPaid(true)
.withFrameworkName(.native)
.appendExternalId("key", "value")
```
}>
```objc
[BidMachineSdk.shared withUserId:@""];
[BidMachineSdk.shared withUserGender:BidMachineUserGenderMale];
[BidMachineSdk.shared withUserYOB:0];
[BidMachineSdk.shared withLocation:[[CLLocation alloc] initWithLatitude:1 longitude:2]];
[BidMachineSdk.shared withCountry:@""];
[BidMachineSdk.shared withCity:@""];
[BidMachineSdk.shared withZip:@""];
[BidMachineSdk.shared withKeywords:@""];
[BidMachineSdk.shared withBlockedApps:@[]];
[BidMachineSdk.shared withBlockedCategories:@[]];
[BidMachineSdk.shared withBlockedAdvertisers:@[]];
[BidMachineSdk.shared withStoreURL:@""];
[BidMachineSdk.shared withStoreId:@""];
[BidMachineSdk.shared withStoreCategory:@""];
[BidMachineSdk.shared withStoreSubCategories:@[]];
[BidMachineSdk.shared withPaid:YES];
[BidMachineSdk.shared withFrameworkName:BidMachineFrameworkNameNative];
[BidMachineSdk.shared appendExternalId:@"key" :@"value"];
```
| Parameter | Type | Description |
|--------------------|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `userId` | `String` | Vendor-specific ID for the user. |
| `userGender` | `BidMachineUserGender` | Gender, one of the following: Female, Male, Unknown. |
| `userYOB` | `UInt32` | Year of birth as a 4-digit integer (e.g. 1990). |
| `userLocation` | `CLLocation` | Location of the user's home base (i.e., not necessarily their current location). |
| `country` | `String` | Country of the user's home base (i.e., not necessarily their current location). |
| `city` | `String` | City of the user's home base (i.e., not necessarily their current location). |
| `zip` | `String` | Zip code of the user's home base (i.e., not necessarily their current location). |
| `keywords` | `String` | List of keywords, interests, or intents. |
| `blockedApps` | `Array` | Block list of apps where ads are disallowed. Use bundle/package names (e.g. `com.foo.mygame`), not App Store IDs. |
| `blockedCategories`| `Array` | Block list of content categories using category IDs. |
| `blockedAdvertisers`| `Array` | Block list of advertisers by their domains (e.g. `example.com`). |
| `storeURL` | `String` | App Store URL for the installed app; required for IQG 2.1 compliance. |
| `storeId` | `String` | Application identifier in the App Store (numeric string, e.g. `"1111"`). |
| `storeCategory` | `String` | Main category of the app in the store (e.g. `"Games"`, `"Lifestyle"`). |
| `storeSubCategories`| `Array` | List of subcategories of the app in the store (e.g. `["Action", "Multiplayer"]`). |
| `paid` | `BOOL` | Indicates whether the app is a paid version (`true`) or free version (`false`). |
| `frameworkName` | `BidMachineFrameworkName`| Name of the framework used (e.g. `Native`, `Unity`). |
### Server Extras
You can get the configuration from the BM server using a pre-agreed key from the server extra parameters.
}>
```swift
let serverExtras = BidMachine.shared.extrasValue(by: "CUSTOM_MEDIATION_KEY")
```
}>
```objc
id value = [BidMachineSdk.shared extrasValueBy:@"CUSTOM_MEDIATION_KEY"];
```
## Auction Request Settings
### Price Floor Parameters
The price floor info is used to set a minimum price for the ad unit, you can pass multiple price floors for one ad request.
:::tip Price Floor Currency
The price floor is always in the US dollars.
:::
}>
```swift
let request = BidMachineSdk.shared.auctionRequest(placement: placement) {
$0.appendPriceFloor(Double(10), UUID().uuidString)
$0.appendPriceFloor(Double(20), UUID().uuidString)
}
```
}>
```objc
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement builder: ^(id _Nonnull builder) {
[builder appendPriceFloor:10.0 identifier:[[NSUUID UUID] UUIDString]];
[builder appendPriceFloor:20.0 identifier:[[NSUUID UUID] UUIDString]];
}];
```
| Parameter | Type | Description |
|----------------|------------|--------------------------------------|
| `priceFloor` | `Double` | Minimum price for ad request |
| `identifier` | `String?` | Unique identifier of the price floor |
## Placement Settings
### Custom Parameters
You can pass custom parameters in the placement object to be sent to the server.
Custom parameters is a dictionary of key-value pairs that can be used for targeting or reporting purposes.
}>
```swift
let placement = try? BidMachineSdk.shared.placement(.banner320x50) {
$0.withCustomParameters([String:Any]())
}
```
}>
```objc
BidMachinePlacement *placement = [BidMachineSdk.shared placement:BidMachineAdFormat.banner320x50
error:nil
builder:^(id _Nonnull builder) {
[builder withCustomParameters:@{}];
}];
```
## Auction Info
The auction info provides details about the ad auction,
including bid ID, creative ID, deal ID, campaign ID,
demand source, price, and custom parameters.
}>
```swift
let bidId = ad.auctionInfo.bidId
let creativeId = ad.auctionInfo.creativeId
let dealId = ad.auctionInfo.dealId
let cId = ad.auctionInfo.cId
let demandSource = ad.auctionInfo.demandSource
let price = ad.auctionInfo.price
let customParams = ad.auctionInfo.customParams
let customExtras = ad.auctionInfo.customExtras
```
}>
```objc
NSString *bidId = banner.auctionInfo.bidId;
NSString *creativeId = banner.auctionInfo.creativeId;
NSString *dealId = banner.auctionInfo.dealId;
NSString *cId = banner.auctionInfo.cId;
NSString *demandSource = banner.auctionInfo.demandSource;
double price = banner.auctionInfo.price;
NSDictionary *customParams = banner.auctionInfo.customParams;
NSDictionary *customExtras = banner.auctionInfo.customExtras;
```
| Parameter | Type | Description |
| -------------- | -------------------------------- | ---------------------------------- |
| `bidId` | `String` | Unique bid identifier |
| `creativeId` | `String?` | Unique creative identifier |
| `dealId` | `String?` | Unique deal identifier |
| `cId` | `String?` | Campaign/grouping ID |
| `demandSource` | `String` | Demand source name |
| `price` | `Double` | Bid price |
| `customParams` | `[String: Any]` / `NSDictionary` | Server custom parameters |
| `customExtras` | `[String: Any]` / `NSDictionary` | Winner unit extras |
## Win/Loss notifications
Call `notifyMediationWin`/`notifyMediationLoss` on the AdRequest instance when BidMachine wins/loses the mediation among networks.
- Win notification:
}>
```swift
BidMachineSdk.shared.notifyMediationWin(ad)
```
}>
```objc
[BidMachineSdk.shared notifyMediationWin:ad];
```
- Loss notification:
}>
```swift
BidMachineSdk.shared.notifyMediationLoss("SOME_NETWORK", 10.0, ad)
```
}>
```objc
[BidMachineSdk.shared notifyMediationLoss:@"SOME_NETWORK" :10.0 :ad];
```
---
## App Privacy Details On The App Store
import { Link } from 'react-router-dom';
# App Privacy Details on the App Store
## Privacy Manifest
### Overview
Privacy Manifest files are now essential for mobile apps under Apple's privacy framework.
BidMachine SDK supports and provides a compliant Privacy Manifest starting from [iOS SDK version 2.5.0](/sdk/general/ios/ios-changelog#version-250-february-14-2024),
ensuring transparency in data practices and alignment with App Store requirements.
### Why Privacy Manifests Matter
- **Apple Policy Compliance**
Apple's [Privacy Manifest requirements](https://developer.apple.com/support/third-party-SDK-requirements/) became mandatory on May 1, 2024.
Any app integrating third-party SDKs without declaring data usage in a manifest risks App Store rejection.
- **User Transparency**
Manifest files clearly communicate to users how data is collected and used,
fostering trust and meeting Apple's privacy nutrition label standards.
- **Streamlined Submission**
With a manifest in place, developers can quickly address privacy questions in App Store Connect, reducing review delays.
- **Privacy Nutrition Labels**
Manifests feed into Apple's privacy nutrition labels, offering concise overviews of an app's data practices to end users.
## Privacy Practices
Since December 8, 2020, all apps submitted to the App Store must declare their privacy practices.
Below is the breakdown of data collection by BidMachine SDK.
| Data Type | Collection | Remarks |
| ------------------------- | :----------: | ------------------------------------------------------------------ |
| **Name** | No | — |
| **Email Address** | No | — |
| **Phone Number** | No | — |
| **Physical Address** | No | — |
| **Other Contact Info** | No | — |
| **Health** | No | — |
| **Fitness** | No | — |
| **Payment Info** | No | — |
| **Credit Info** | No | — |
| **Other Financial Info** | No | — |
| **Precise Location** | Optional | Collected only if the host app holds `NSLocationWhenInUse`/`Always` permission granted by the user and location tracking is enabled; the SDK never requests this permission itself |
| **Coarse Location** | Optional | Collected only if the host app holds location permission and location tracking is enabled |
| **Sensitive Info** | No | — |
| **Contacts** | No | — |
| **Emails / Text Messages**| No | — |
| **Photos / Videos** | No | — |
| **Audio Data** | No | — |
| **Gameplay Content** | No | — |
| **Customer Support** | No | — |
| **Other User Content** | No | — |
| **Browsing History** | No | — |
| **Search History** | No | — |
| **User ID** | Yes | Used for advertising targeting |
| **Device ID** | Yes | Used for advertising targeting |
| **Purchase History** | No | — |
| **Product Interaction** | No | — |
| **Advertising Data** | Yes | Used for advertising targeting |
| **Other Usage Data** | No | — |
| **Crash Data** | Yes | Collected for stability monitoring |
| **Performance Data** | Yes | Collected to optimize SDK performance |
| **Other Diagnostic Data** | No | — |
| **Other Data Types** | Yes | Technical device info, network info, carrier user ID, etc. |
---
## Banner Ads
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjcLabel from "@site/src/components/code-labels/objc";
## Ad Request
### Placement
Create placement from `AdFormat` with your parameters:
}>
```swift
let placement = try? BidMachineSdk.shared.placement(.banner320x50) {
$0.withPlacementId("")
$0.withCustomParameters([String:Any]())
}
```
}>
```objc
NSError *error = nil;
BidMachinePlacement *placement = [BidMachineSdk.shared placement:BidMachineAdFormat.banner320x50
error:&error
builder:^(id _Nonnull builder) {
[builder withPlacementId:@""];
[builder withCustomParameters:@{}];
}];
```
| Parameter | Type | Description |
| -------------------- | -------------------------------- | ---------------------------------- |
| `placementId` | `String` | Placement ID |
| `customParameters` | `[String: Any]` / `NSDictionary` | Passed directly to the server |
#### AdFormat
The placement format is defined by static properties of the `AdFormat` class:
}>
```swift
@objc(BidMachineAdFormat)
final public class AdFormat : NSObject {
@objc public static var banner320x50: BidMachine.AdFormat { get }
@objc public static var banner728x90: BidMachine.AdFormat { get }
@objc public static var banner300x250: BidMachine.AdFormat { get }
@objc public static func bannerAdaptive(width: UInt32, maxHeight: UInt32) -> BidMachine.AdFormat
}
```
}>
```objc
@interface BidMachineAdFormat (SWIFT_EXTENSION(BidMachine))
+ (BidMachineAdFormat * _Nonnull)banner320x50;
+ (BidMachineAdFormat * _Nonnull)banner728x90;
+ (BidMachineAdFormat * _Nonnull)banner300x250;
+ (BidMachineAdFormat * _Nonnull)bannerAdaptiveWithWidth:(uint32_t)width maxHeight:(uint32_t)maxHeight;
@end
```
#### Available banner formats
| Format | Description |
| ----------------------- | ---------------------------------------------------- |
| `banner320x50` | Standard 320×50 banner |
| `banner728x90` | Leaderboard 728×90 banner |
| `banner300x250` | Medium rectangle 300×250 banner |
| `bannerAdaptive` | Adaptive banner with custom width and max height |
:::info Adaptive Banner Height
When using `bannerAdaptive`, the `maxHeight` parameter defaults to `0` if not specified. A value of `0` acts as a wildcard, allowing the banner to use any height based on the ad content.
:::
}>
```swift
// Adaptive banner with width 320 and wildcard height
let placement = try? BidMachineSdk.shared.placement(.bannerAdaptive(width: 320))
// Or with specific max height
let placement = try? BidMachineSdk.shared.placement(.bannerAdaptive(width: 320, maxHeight: 50))
```
}>
```objc
// Adaptive banner with width 320 and wildcard height
BidMachineAdFormat *format = [BidMachineAdFormat bannerAdaptiveWithWidth:320 maxHeight:0];
BidMachinePlacement *placement = [BidMachineSdk.shared placement:format error:&error builder:nil];
// Or with specific max height
BidMachineAdFormat *format = [BidMachineAdFormat bannerAdaptiveWithWidth:320 maxHeight:50];
BidMachinePlacement *placement = [BidMachineSdk.shared placement:format error:&error builder:nil];
```
:::info Calculating Adaptive Height
Use `BidMachineBannerSize.getMaxAdaptiveHeight(width:)` to calculate the maximum expected banner height for a given width. Both parameter and return value are in density-independent points.
:::
}>
```swift
// Get screen width in points
let screenWidthPt = UInt32(UIScreen.main.bounds.width)
// Calculate maximum adaptive height for screen width
let maxHeightPt = BidMachineBannerSize.getMaxAdaptiveHeight(width: screenWidthPt)
// Create adaptive banner with calculated dimensions
let placement = try? BidMachineSdk.shared.placement(.bannerAdaptive(width: screenWidthPt, maxHeight: maxHeightPt))
```
}>
```objc
// Get screen width in points
uint32_t screenWidthPt = (uint32_t)UIScreen.mainScreen.bounds.size.width;
// Calculate maximum adaptive height for screen width
uint32_t maxHeightPt = [BidMachineBannerSize getMaxAdaptiveHeightWithWidth:screenWidthPt];
// Create adaptive banner with calculated dimensions
BidMachineAdFormat *format = [BidMachineAdFormat bannerAdaptiveWithWidth:screenWidthPt maxHeight:maxHeightPt];
BidMachinePlacement *placement = [BidMachineSdk.shared placement:format error:&error builder:nil];
```
### General Request
Auction request is used to set bidding parameters: The request is created with a special placement and your parameters
}>
```swift
let request = BidMachineSdk.shared.auctionRequest(placement: placement) {
$0.withUnitConfigurations([BidMachineUnitConfiguration]())
$0.appendPriceFloor(Double(10), UUID().uuidString)
}
```
}>
```objc
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement
builder:^(id _Nonnull builder) {
[builder withUnitConfigurations:@[]];
[builder appendPriceFloor:10.0 identifier:[[NSUUID UUID] UUIDString]];
}];
```
| Parameter | Type | Description |
| -------------------- | -------------------------------- | ---------------------------------- |
| `unitConfigurations` | `[BidMachineUnitConfiguration]` | Header bidding unit configurations |
| `priceFloor` | `(Double, String)` | Price floor (value and identifier) |
### Client Bidding Request
#### Bid Token
With S2S integration, you will need a **token** that you need to transfer in the request. To get a **token**, you can use method:
}>
```swift
BidMachineSdk.shared.token(placement: placement) { token in }
```
}>
```objc
[BidMachineSdk.shared tokenWithPlacement:placement completion:^(NSString *token) {
}];
```
#### Bid Payload
After completing the server-side auction, you will receive a Base64-encoded payload string, which must be passed as a parameter to the AuctionRequest.
}>
```swift
let request = BidMachineSdk.shared.auctionRequest(placement: placement) {
$0.withPayload("")
}
```
}>
```objc
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement
builder:^(id _Nonnull builder) {
[builder withPayload:@""];
}];
```
| Parameter | Type | Description |
| -------------------- | ----------------------------------- | ----------------------------------------- |
| `payload` | `String` | Custom BidMachine payload string |
## Ad Display
The ad object handles downloading and displaying ads.
### Prepare the ad object
Request an ad using your auction request:
}>
```swift
BidMachineSdk.shared.banner(request: request) { [weak self] ad, error in
guard let self else { return }
self.banner = ad
}
```
}>
```objc
__weak typeof(self) weakSelf = self;
[[BidMachineSdk shared] bannerWithRequest:request
completion:^(BidMachineBanner *ad, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
strongSelf.banner = ad;
}];
```
The loaded ad contains `auctionInfo` and `requestInfo`.
:::success Auction Info
The `auctionInfo` contains information about the auction, such as the winning bidder, price, and other relevant details.
The `auctionInfo` is described [here](/sdk/general/ios/advanced#auction-info).
:::
### Delegate
Assign the delegate to receive ad events:
}>
```swift
ad.delegate = self
```
}>
```objc
ad.delegate = self;
```
Implement `BidMachineAdDelegate` methods:
}>
```swift
func didLoadAd(_ ad: BidMachineAdProtocol) {}
func didFailLoadAd(_ ad: BidMachineAdProtocol, _ error: Error) {}
func didPresentAd(_ ad: BidMachineAdProtocol) {}
func didFailPresentAd(_ ad: BidMachineAdProtocol, _ error: Error) {}
func didDismissAd(_ ad: BidMachineAdProtocol) {}
func willPresentScreen(_ ad: BidMachineAdProtocol) {}
func didDismissScreen(_ ad: BidMachineAdProtocol) {}
func didUserInteraction(_ ad: BidMachineAdProtocol) {}
func didExpired(_ ad: BidMachineAdProtocol) {}
func didTrackImpression(_ ad: BidMachineAdProtocol) {}
func didTrackInteraction(_ ad: BidMachineAdProtocol) {}
func didReceiveReward(_ ad: BidMachineAdProtocol) {}
```
}>
```objc
- (void)didLoadAd:(id)ad {}
- (void)didFailLoadAd:(id)ad :(NSError *)error {}
- (void)didPresentAd:(id)ad {}
- (void)didFailPresentAd:(id)ad :(NSError *)error {}
- (void)didDismissAd:(id)ad {}
- (void)willPresentScreen:(id)ad {}
- (void)didDismissScreen:(id)ad {}
- (void)didUserInteraction:(id)ad {}
- (void)didExpired:(id)ad {}
- (void)didTrackImpression:(id)ad {}
- (void)didTrackInteraction:(id)ad {}
- (void)didReceiveReward:(id)ad {}
```
#### Get loaded ad size
`BidMachineBanner.adSize` returns the `BidMachineBannerSize` received from the ad response. Access it in `didLoadAd` to get the actual width and height of the creative:
}>
```swift
func didLoadAd(_ ad: BidMachineAdProtocol) {
guard let banner = ad as? BidMachineBanner else { return }
let loadedSize = banner.adSize
let width = loadedSize.width
let height = loadedSize.height
}
```
}>
```objc
- (void)didLoadAd:(id)ad {
BidMachineBanner *banner = (BidMachineBanner *)ad;
BidMachineBannerSize *loadedSize = banner.adSize;
uint32_t width = loadedSize.width;
uint32_t height = loadedSize.height;
}
```
### Loading and presenting ads
:::warning Loading prerequisites
Make sure both the `delegate` and `controller` are set before loading.
:::
Example of banner ad loading:
}>
```swift
guard let placement = try? BidMachineSdk.shared.placement(.banner320x50) else { return }
let request = BidMachineSdk.shared.auctionRequest(placement: placement)
BidMachineSdk.shared.banner(request: request) { [weak self] ad, error in
guard let self = self else {
return
}
self.banner = ad
ad.controller = self
ad.delegate = self
ad.loadAd()
}
```
}>
```objc
NSError *error = nil;
BidMachinePlacement *placement = [BidMachineSdk.shared placement:BidMachineAdFormat.banner320x50
error:&error
builder:nil];
if (!placement) {
return;
}
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement
builder:nil];
__weak typeof(self) weakSelf = self;
[[BidMachineSdk shared] bannerWithRequest:request
completion:^(BidMachineBanner *ad, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
strongSelf.banner = ad;
ad.controller = strongSelf;
ad.delegate = strongSelf;
[ad loadAd];
}];
```
Present the banner ad:
}>
```swift
self.view.addSubview(banner)
```
}>
```objc
[self.view addSubview:self.banner];
```
---
## Changelog(3)
## Version 3.8.0 (August 25th, 2026)
### Added
- Added PiP (Picture-in-Picture) mode in Adaptive Rendering
### Changed
- Updated MRAID WebView handling for iOS 26
- Improved ad request reliability
- Improved privacy and regulation handling
### Bug fixes
- Fixed video playback issues
- Stability improvements and crash fixes
## Version 3.7.1 (May 29th, 2026)
### Bug fixes
- Fixed ad dismiss handling and event reporting in certain presentation scenarios
- Fixed click handling for banner ads rendered inside native ad placements
## Version 3.7.0 (May 11th, 2026)
### Added
- Added a new flat configuration API on `BidMachineSdk.shared`.
SDK, regulation, publisher, targeting, store, and bidding settings can now be configured directly on `BidMachineSdk.shared` using chainable `with...` methods, without nested `populate` calls.
```swift
BidMachineSdk.shared
.withTestMode(true)
.withGDPRZone(true)
.withNonPersonalized(true)
.withPubDomain("example.com")
.withUserId("user_id")
```
- Added `withNonPersonalized(_:)` regulation setting.
This setting allows publishers to explicitly mark ad requests as non-personalized when applicable.
### Changed
- Updated Open Measurement integration to v1.6.3.
- Improved internal privacy and regulation handling.
### Deprecated
- Deprecated nested configuration entry points on `BidMachineInfoProtocol`:
- `publisherInfo`
- `targetingInfo`
- `regulationInfo`
- `biddingInfo`
- `populate(_:)`
Use the new flat `BidMachineSdk.shared.with...` API instead.
### Migration
#### Regulation
```swift
// Before
BidMachineSdk.shared.regulationInfo.populate {
$0.withCOPPA(true)
$0.withGDPRZone(true)
}
// After
BidMachineSdk.shared
.withCOPPA(true)
.withGDPRZone(true)
```
#### Targeting
```swift
// Before
BidMachineSdk.shared.targetingInfo.populate {
$0.withUserId("user_id")
}
// After
BidMachineSdk.shared.withUserId("user_id")
```
### Notes
- Regulation state is resolved using IAB TCF v2 data and publisher-provided regulation settings.
IAB TCF v1 data is not used when resolving the SDK regulation result.
- `withNonPersonalized(_:)` can be used to explicitly mark ad requests as non-personalized when applicable.
- `BidMachineSdk.partnerName` is no longer part of the public API.
- `BidMachineSdk.partnerVersion` is no longer part of the public API.
## Version 3.6.1 (March 23rd, 2026)
### Bug fixes
- Fixed **Privacy Manifest** undeclared reasons warning
- Fixed a potential crash in `AdaptiveVideoPlayerBufferingObserver` class
## Version 3.6.0 (March 11th, 2025)
### Features
- New configurable viewability tracking system based on ViewabilityConfiguration rules, supporting MRC standard and custom viewability definitions with geometry, visibility, overlap, and lifecycle metrics.
- Viewability measurement now works correctly in SwiftUI-based view hierarchies
- Smoother transition animations when pressing the collapse button in MRAID expand scenarios
- Adaptive Rendering now tracks view cycle for scrollable content
### Bug fixes
- Verified and fixed rendering behavior with iPad OS 26 multitasking
- Fixed SDK integration issues in Unity apps
- Fixed crash in STKNetworkReachability module
## Version 3.5.1 (December 11th, 2025)
### Features
- Added `BidMachineBannerSize.getMaxAdaptiveHeight(width:)` API to calculate maximum expected banner height for a given width
- Pure static stack modules dependencies
- Updated OMSDK to version 1.6.0 with static/dynamic versions support
## Version 3.5.0 (Oct 22nd, 2025)
### Features
- Adaptive banner support
- New AdFormat API
- Updated Placement API
- MRAID Expand Support
- iOS26 support
### API Changes & Deprecations
#### New AdFormat API
Introduced `AdFormat` class to replace the deprecated `PlacementFormat` enum:
```swift
@objc(BidMachineAdFormat)
public final class AdFormat : NSObject {
// Banner formats
@objc public static var banner320x50: BidMachine.AdFormat { get }
@objc public static var banner728x90: BidMachine.AdFormat { get }
@objc public static var banner300x250: BidMachine.AdFormat { get }
@objc public static func bannerAdaptive(width: UInt32, maxHeight: UInt32) -> BidMachine.AdFormat
// Interstitial formats
@objc public static var interstitial: BidMachine.AdFormat { get }
@objc public static var interstitialStatic: BidMachine.AdFormat { get }
@objc public static var interstitialVideo: BidMachine.AdFormat { get }
// Rewarded formats
@objc public static var rewarded: BidMachine.AdFormat { get }
@objc public static var rewardedStatic: BidMachine.AdFormat { get }
@objc public static var rewardedVideo: BidMachine.AdFormat { get }
// Native formats
@objc public static var native: BidMachine.AdFormat { get }
@objc public static var nativeIcon: BidMachine.AdFormat { get }
@objc public static var nativeImage: BidMachine.AdFormat { get }
@objc public static var nativeVideo: BidMachine.AdFormat { get }
@objc public static var nativeIconAndVideo: BidMachine.AdFormat { get }
@objc public static var nativeIconAndImage: BidMachine.AdFormat { get }
@objc public static var nativeImageAndVideo: BidMachine.AdFormat { get }
}
```
#### Updated Placement API
**Deprecated:**
```swift
// Old API (deprecated since 3.5.0)
let placement = try? BidMachineSdk.shared.placement(from: .banner) { ... }
```
**New:**
```swift
// New API
let placement = try? BidMachineSdk.shared.placement(.banner320x50) { ... }
```
#### Migration Guide
**Swift:**
```swift
// Before (deprecated)
let placement = try? BidMachineSdk.shared.placement(from: .banner) {
$0.withPlacementId("placement_id")
}
// After
let placement = try? BidMachineSdk.shared.placement(.banner320x50) {
$0.withPlacementId("placement_id")
}
```
**Objective-C:**
```objc
// Before (deprecated)
BidMachinePlacement *placement = [[BidMachineSdk shared]
placementFrom:BidMachinePlacementFormatBanner
error:&error
builder:nil];
// After
BidMachinePlacement *placement = [BidMachineSdk.shared
placement:BidMachineAdFormat.banner320x50
error:&error
builder:nil];
```
#### Deprecated APIs
The following APIs are deprecated since version 3.5.0 and will be removed in future releases:
| Deprecated API | Replacement | Notes |
|----------------|-------------|-------|
| `PlacementFormat` enum | `AdFormat` class | Use static properties of `AdFormat` |
| `placement(from:builder:)` | `placement(_:builder:)` | Parameter changed from `from:` to direct argument |
| `NSString.bidmachine_placement_format` | `AdFormat` static properties | String conversion no longer supported |
## Version 3.4.0 (Aug 7th, 2025)
### Features
- Reverted `OMSDK` to 1.5.2
- Watermarks support in Adaptive Rendering
- Minor bug fixes and performance improvements
## Version 3.3.0 (May 26th, 2025)
### Features & API Changes
- Added detection for broken creatives to improve reliability
- Added support for Custom Product Pages via SKProductController
- Implemented adaptive background rendering
- Improved adaptive animation rendering
- Fixed issue with AVPlayer not maintaining correct active state
- **New Public API**:
Introduced `BidMachinePlacement`
```swift
@objc public final class BidMachinePlacement: NSObject {
@objc public fileprivate(set) var format: PlacementFormat
@objc public fileprivate(set) var placementId: String?
@objc public fileprivate(set) var customParameters = [String: Any]()
}
```
- **New Public API**:
Introduced `BidMachineAuctionRequest` to replace the deprecated `BidMachineRequestInfoProtocol`
```swift
@objc public final class BidMachineAuctionRequest: NSObject {
public fileprivate(set) var payload: String?
public fileprivate(set) var priceFloors = [BidMachinePriceFloorProtocol]()
public fileprivate(set) var unitsConfigurations = [BidMachineBiddingUnitConfiguration]()
}
```
- **New Builder Functions**:
- Create placement:
```swift
func placement(from format: PlacementFormat, builder: BidMachinePlacementBuilderBlock? = nil) throws -> BidMachinePlacement
```
- Create auction request:
```swift
func auctionRequest(placement: BidMachinePlacement, builder: BidMachineAuctionRequestBuilderBlock? = nil) -> BidMachineAuctionRequest
```
- Generate token:
```swift
func token(placement: BidMachinePlacement, completion: @escaping (String?) -> Void)
```
- **Placement Parameters Support**:
`placementId` and `customParameters` are now passed in token and RTB requests.
### Refactoring
- `PlacementFormat` moved to new public class `BidMachinePlacementConfiguration`, all related APIs updated.
- `BidMachine.Placement` has been replaced with `adType: PlacementType`.
### Deprecations
- `Placement` struct is deprecated:
```swift
@available(*, deprecated, message: "Will be removed")
public struct Placement: Equatable
```
- `BidMachineRequestInfoProtocol` is deprecated in favor of `BidMachineAuctionRequest`.
- Deprecated token API:
```swift
@available(*, deprecated, message: "Use token(placement:completion:) instead.")
func token(with format: PlacementFormat, completion: @escaping (String?) -> Void)
```
- Deprecated request configuration API:
```swift
@available(*, deprecated, message: "Use auctionRequest(placement:builder:) instead.")
func requestConfiguration(_ format: PlacementFormat) throws -> BidMachineRequestConfigurationProtocol
```
## Version 3.2.1 (Mar 21st, 2025)
**Features**:
- Added COPPA trafic idfv/idfa restrictions
- OMSDK version `1.5.4`
- Added CRID Info to Crash Report
- Added `IMPRESSION_OPPORTUNITY` event tracking
## Version 3.2.0 (Feb 12th, 2025)
**Features**:
- Added support for `ERID` requirements
- Added `Deep Links` support
- Added `User-Agent` to trackers
- Improved Referrer HTTP header field for `MRAID` ad
**Bug fixes**:
- Fixed `iOS 14.6-14.9` Swift Concurrency crashes
- Fixed SKAN 4.0 Ad impression init fix for Mac OS
- `STKVastController` fixed: crash + store opening with postbanner
- Changed analytics DB file path
## Version 3.1.2 (December 17, 2024)
- Fix potential crash in `ProtoBuilder.Context.Session.with(environment:contextualDatas:)`
- Fix Main Thread Checker warning on `-[UIApplication canOpenURL:]`
## Version 3.1.1 (November 19, 2024)
- Fix bug introduced in 3.1.0 that prevented impressions firing for view ads in some cases
- Extend MRAID feature support
- Internal stability improvements
## Version 3.1.0 (October 31, 2024)
:::warning
Updated the minimum supported Xcode version to **15.3**
:::
- Internal stability improvements
- Certified with OM SDK 1.5.2
- Adopt AdAttributionKit
- Fix OOM crash in `+[STKVASTUtilities blurredImageWithImage:]`
- Improve viewability for banner ads
## Version 3.0.1 (September 12, 2024)
- Add **first_launch_time**
- Fix MRAID placeholder behavior
- Fix potential crash on iOS 12
## Version 3.0.0 (July 22, 2024)
:::warning
Updated the minimum supported Xcode version to **15.2**
:::
- Drop support for iOS versions below 13 (SDK code will not execute on earlier versions)
- Remove deprecated Rich Media Ad format
- Update OMSDK to 1.5.0
## Version 2.7.0 (May 7, 2024)
- Fix banner disappearing when moving through the view hierarchy
- General bug fixes and improvements
- Add support for dynamic framework integration
## Version 2.6.1 (April 19, 2024)
- Fix UI thread lock issue
- Fix Thread Sanitizer warnings
## Version 2.6.0 (April 5, 2024)
- Update OMSDK to 1.4.12 (certified)
- Performance enhancements and various fixes
## Version 2.5.3 (March 25, 2024)
- Update XCPrivacy Manifest
## Version 2.5.2 (March 19, 2024)
**Features:**
- General bug fixes and improvements
## Version 2.5.1 (February 20, 2024)
**Features:**
- Add support for Google Mobile Ads SDK 11.x
## Version 2.5.0 (February 14, 2024)
:::warning
Updated the minimum supported Xcode version to **14.3**
Supported Google Mobile Ads SDK version ≥ 10.0 (see 2.5.1 for unrecognized selector fix)
:::
**Features:**
- Add PrivacyManifest file
**Bugfixes:**
- Fix StoreKit on iOS 17
## Version 2.4.0.4 (February 20, 2024)
**Features:**
- Support Google Mobile Ads SDK 11.x
## Version 2.4.0.3 (January 26, 2024)
:::warning
Supported Google Mobile Ads SDK version ≥ 10.0 (see 2.4.0.4 for update)
:::
**Features:**
- Internal improvements
## Version 2.4.0.2 (January 4, 2024)
**Features:**
- Append skip initialization flag
## Version 2.4.0.1 (November 30, 2023)
**Features:**
- Add SKOverlay support for MRAID
## Version 2.4.0.0 (November 9, 2023)
**Features:**
- Add GPP support
**Bugfixes:**
- Fix SKOverlay logic
- Fix memory leaks in bidding integrations
- Fix SDK initialization crashes
- Resolve Swift protobuf conflict with SPM
## Version 2.3.0.3 (February 20, 2024)
**Features:**
- Support Google Mobile Ads SDK 11.x
## Version 2.3.0.2 (August 10, 2023)
:::warning
Supported Google Mobile Ads SDK version ≥ 10.0 (see 2.3.0.3 for update)
:::
**Features:**
- Improved Google integration
## Version 2.3.0.1 (July 25, 2023)
**Features:**
- Add Rewarded/MREC ad types in Google integration
## Version 2.3.0.0 (June 26, 2023)
**Features:**
- Check network reachability
- Append failure callback for AdView types
- Update dependency management system
- Miscellaneous improvements
**Bugfixes:**
- Fix WKWebView main thread bug
## Version 2.1.0.0 (May 22, 2023)
- Add new token method
- Bump Proto Core to 0.3.0
- Bump API Core to 0.3.0
- Bump Network Core to 0.3.0
- Bump Display Core to 0.4.0
- Bump Bidding Core to 0.3.0
- Bump Analytics Core to 0.4.0
- Bump IAB to 2.1.0
- Bump StackModules to 1.5.0
## Version 2.0.1.0 (April 18, 2023)
- Bump Proto Core to 0.2.0
- Bump API Core to 0.2.0
- Bump Network Core to 0.2.0
- Bump Display Core to 0.3.0
- Bump Bidding Core to 0.2.0
- Bump Analytics Core to 0.3.0
- Increase minimum iOS version to 12.0
- Remove armv7 and i386 support (deprecated)
- Improve loading, presentation, feature, event, and error logic
- Include SK fields in tokens
- Fix arithmetic overflow exception
- Fix banner left alignment
- Trigger `didUserInteraction` before `willPresentScreen`
- Update license to Commercial
## Version 2.0.0.6 (March 10, 2023)
- Update license to Commercial
## Version 2.0.0.5 (December 29, 2022)
- Bump StackModules to 1.4.0
## Version 2.0.0.4 (November 16, 2022)
- Bump IAB to 2.0.0
## Version 2.0.0.3 (November 8, 2022)
- Bump Display Core to 0.1.0
- Add `canShow` method
## Version 2.0.0.2 (November 3, 2022)
- Bump API Core to 0.0.3
- Bump Analytics Core to 0.1.0
## Version 2.0.0.1 (October 6, 2022)
- Update IAB adapters
- Bump API Core to 0.0.2
- Bump Display Core to 0.0.2
- Bump Bidding Core to 0.0.2
- Bump IAB to 1.9.0
- Append Analytics Core 0.0.1
## Version 2.0.0.0 (September 7, 2022)
- Update project structure
- Update public API
- Append adapter caching
## Version 1.9.4.8 (August 16, 2022)
- Update proto model to 0.8.2
- Include regulation info in tokens
## Version 1.9.4.7 (August 11, 2022)
- Fix request multithreading crash
## Version 1.9.4.6 (August 9, 2022)
- Small improvements
- Update initial request URL
- Fix potential Native crash
## Version 1.9.4.5 (July 25, 2022)
- Update network registration logic
## Version 1.9.4.4 (July 14, 2022)
- Update impression callback logic
## Version 1.9.4.3 (June 30, 2022)
- Allow biddingToken before initialization
- Improve ad caching
## Version 1.9.4.2 (June 22, 2022)
- Update SDK initialization callback
## Version 1.9.4.1 (June 14, 2022)
- Fix Skippable Video controller
## Version 1.9.4.0 (June 3, 2022)
- Update Ad Caching logic
- Update Ad display controllers
- Deprecate Any AdRequest methods
- Deprecate Any AdDisplay methods
- Add additional loading method for AdDisplay
## Version 1.9.3.1 (May 30, 2022)
- Add hashed request initialization
## Version 1.9.3.0 (May 6, 2022)
- Bump StackProtobuf to 0.8.1
- Bump StackModules to 1.2.1
- Update network configuration initialization
- Update placement type for fullscreen extensions
## Version 1.9.2.1 (March 23, 2022)
- Bump StackProtobuf to 0.8.0
## Version 1.9.2.0 (March 18, 2022)
- Bump StackModules to 1.2.0
## Version 1.9.1.0 (February 24, 2022)
- Convert BidMachine SDK to XCFramework
- Bump StackAPI to 0.7.1
- Bump StackModules to 1.1.11
## Version 1.9.0.2 (February 22, 2022)
- Fix event handling
## Version 1.9.0.1 (February 8, 2022)
- Append request custom parameters
## Version 1.9.0.0 (February 1, 2022)
- Append bidding token
## Version 1.9.0.0-Beta.0.0 (November 23, 2021)
- Append request cacher
## Version 1.8.0.3 (December 17, 2021)
- Update event tracking logic
## Version 1.8.0.2 (December 16, 2021)
- Append request storage comparison
## Version 1.8.0.1 (November 23, 2021)
- Fix event escaping string
## Version 1.8.0.0 (October 26, 2021)
- Append RichMediaView Type
## Version 1.7.4.2 (October 26, 2021)
- Append Waterfall + HB adapter support
## Version 1.7.4.1 (October 21, 2021)
- Append request loss parameters
## Version 1.7.4.0 (October 8, 2021)
- Append native ad event tracking
## Version 1.7.3.6 (August 24, 2021)
- Fix potential multithreading exception
## Version 1.7.3.5 (August 3, 2021)
- Fix URL session protobuf conflict
## Version 1.7.3.4 (July 28, 2021)
- Update C++ support
## Version 1.7.3.3 (July 20, 2021)
- SDK improvements
## Version 1.7.3.2 (May 25, 2021)
- Add API for placement ID transfer
## Version 1.7.3.1 (May 14, 2021)
- Add API for external user IDs transfer
- Fix thread-unsafe calls
- Fix video payload validation
## Version 1.7.3.0 (April 20, 2021)
- Append SKAdNetwork 2.2 support
- Append OM MRAID/VAST support
- Various small fixes
## Version 1.7.2.0 (April 12, 2021)
- Append bid payload
## Version 1.7.1.0 (March 30, 2021)
- SDK improvements
- Update header bidding configuration method
- Separate adapters into a dedicated project
- Deprecate client-side rounding (use server-side)
- Deprecated BDMFetcher: use BDMRequestStorage for request persistence
---
## Info.plist & Permissions
## Overview
BidMachine SDK does not require any iOS permissions.
The SDK never requests access to tracking, location, camera, microphone, photos,
calendar, or any other protected system resource. As a result, BidMachine does not
require any permission-related entries in your application's `Info.plist`.
If your project already contains permission usage descriptions, they were most likely
added by your application, another SDK, or a build script. Keep only the keys required by
features your app actually uses.
## Permission Usage Descriptions
Include a usage description only when your application itself uses the corresponding
feature. Each key you include should describe that feature in terms a user would
recognize.
One key deserves special mention:
:::note App Tracking Transparency
BidMachine reads the current ATT authorization status if available, but never requests
tracking authorization itself. If another component in your app presents the ATT dialog,
you must include `NSUserTrackingUsageDescription`. See
[App Tracking Transparency](/sdk/general/ios/overview#app-tracking-transparency).
:::
## App Store Review
Apple reviews permission usage descriptions under
[App Store Review Guideline 5.1.1](https://developer.apple.com/app-store/review/guidelines/#data-collection-and-storage).
Purpose strings must explain a user-facing feature of your app rather than
advertising-related functionality.
If your app doesn't use a permission, remove the corresponding `Info.plist` key instead of
providing a generic or placeholder description.
| Purpose string | Outcome |
| --- | --- |
| `"We use your location to show nearby stores and local content."` | Describes a user-facing feature |
| `"Your location will be used to provide you an ad in location."` | Describes advertising only |
| `"-"` | Placeholder |
## Permission Reference
| Permission | BidMachine | Recommendation |
| --- | :---: | --- |
| Tracking (ATT) | Not required | Include `NSUserTrackingUsageDescription` if your app or any other component presents the ATT dialog. BidMachine reads the resulting status but never requests authorization itself. |
| Location | Not required | Include only if your app provides location-based features. BidMachine uses location information only when permission has already been granted by your application. |
| Calendar | Not required | Include only if your application accesses the user's calendar. |
| Photos | Not required | Include only if your application reads from or writes to the photo library. |
| Camera & Microphone | Not required | Include only if your application captures photos, video, or audio. |
:::info MRAID calendar and photo features
BidMachine's distributed iOS SDK does not include MRAID calendar or store-picture
support. Adding calendar or photo library permission keys will not enable this
functionality, so these keys should only be present if your application uses the
Calendar or Photos frameworks.
:::
Technical details
The MRAID `createCalendarEvent` and `storePicture` code paths are guarded by the
`MRAID_CALENDAR_ENABLED` and `MRAID_STORE_PICTURE_ENABLED` compile-time flags, which are
defined only in debug configurations. The published XCFrameworks therefore contain no
`EventKit`, `EventKitUI`, or `Photos` symbols.
The SDK likewise links no camera or microphone APIs. The only `AVFoundation` usage is the
read-only `AVAudioSession.isOtherAudioPlaying` contextual signal, which requires no
permission.
## Unity Integration Notes
Some Unity post-process build scripts add permission usage descriptions automatically.
The following pattern is common and worth reviewing, since the location strings describe
advertising rather than an app feature, and the calendar value is a placeholder:
```csharp
plistRoot.SetString("NSLocationAlwaysUsageDescription", "Your location will be used to provide you an ad in location.");
plistRoot.SetString("NSLocationWhenInUseUsageDescription", "Your location will be used to provide you an ad in location.");
plistRoot.SetString("NSCalendarsUsageDescription", "-");
```
If your app does not use location or calendar features, remove these keys from the
script. If it does, replace the strings with descriptions of the corresponding app
feature.
## Troubleshooting
If App Store Connect reports a missing permission usage description, you can verify which
framework references the corresponding API using the following commands.
```sh
# Check whether the BidMachine framework references the API
nm -u BidMachine.framework/BidMachine | grep -iE 'EKEventStore|PHPhotoLibrary|AVCaptureDevice|requestTrackingAuthorization'
# List frameworks linked by your app
otool -L YourApp.app/YourApp | grep -iE 'EventKit|Photos|AppTrackingTransparency|CoreLocation'
```
For a missing privacy manifest, confirm the manifest reached your app bundle. Xcode's
**Organizer → Archives → Generate Privacy Report** is the most reliable check; for
CocoaPods integrations, `pod deintegrate && pod install` resolves most cases. See
[Privacy Manifest](/sdk/general/ios/overview#privacy-manifest).
## Optional URL Scheme Support
MRAID creatives may include `tel:` and `sms:` links. Support for these is detected with
`UIApplication.canOpenURL`, which requires the scheme to be declared in
`LSApplicationQueriesSchemes`. Declaring them enables click-through on such creatives and
has no effect on App Store review.
```xml title="Info.plist"
LSApplicationQueriesSchemestelsmsitms-apps
```
## Application Metadata
| Key | Notes |
| --- | --- |
| `CFBundleShortVersionString` / `CFBundleVersion` | Use a valid SemVer `X.Y.Z` value (`2.7.0`, not `2.70`). Non-SemVer values have been observed to prevent SKAdNetwork items from initializing. If an embedded framework such as `UnityFramework.framework` omits these keys, upload validation fails — add them to that framework's own `Info.plist`. |
| `ITSAppUsesNonExemptEncryption` | Set to `false` to skip Apple's export-compliance question on each upload, if your app uses no non-exempt encryption. |
## Monetization Configuration
These keys are not permissions, but the SDK reads them from your `Info.plist` and they
affect attribution and demand.
| Key | Purpose |
| --- | --- |
| `SKAdNetworkItems` | Required for install attribution. Keep the list current — an outdated list is reported in the dashboard as *"SKAdNetwork Items are missing / outdated"* and reduces the demand available to your inventory. Partner IDs change independently of the SDK version, so re-check the list at each update. See [SKAdNetwork Support](/sdk/general/ios/overview#skadnetwork-support). |
| `AdNetworkIdentifiers` | AdAttributionKit network identifiers, forwarded to buyers in the bid request. See [AdAttributionKit Support](/sdk/general/ios/overview#adattributionkit-support). |
| `NSAdvertisingAttributionReportEndpoint` | Endpoint for copies of attribution postbacks. Include only if you operate one. |
## Network Security
`NSAppTransportSecurity` with `NSAllowsArbitraryLoads` enabled allows non-HTTPS creatives
by signalling HTTP support in the bid request. Apple asks for a justification for
arbitrary loads during review, so include it only if your app requires it. Leaving App
Transport Security at its default is the recommended production configuration. See
[Network security configuration](/sdk/general/ios/overview#network-security-configuration).
---
## Interstitial Ads(Ios)
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjcLabel from "@site/src/components/code-labels/objc";
## Ad Request
### Placement
Create placement from `AdFormat` with your parameters:
}>
```swift
let placement = try? BidMachineSdk.shared.placement(.intersitial) {
$0.withPlacementId("")
$0.withCustomParameters([String:Any]())
}
```
}>
```objc
NSError *error = nil;
BidMachinePlacement *placement = [BidMachineSdk.shared placement:BidMachineAdFormat.interstitial
error:&error
builder:^(id _Nonnull builder) {
[builder withPlacementId:@""];
[builder withCustomParameters:@{}];
}];
```
| Parameter | Type | Description |
| -------------------- | -------------------------------- | ---------------------------------- |
| `placementId` | `String` | Placement ID |
| `customParameters` | `[String: Any]` / `NSDictionary` | Passed directly to the server |
#### AdFormat
The placement format is defined by static properties of the `AdFormat` class:
}>
```swift
@objc(BidMachineAdFormat)
final public class AdFormat : NSObject {
@objc public static var interstitial: BidMachine.AdFormat { get }
@objc public static var interstitialStatic: BidMachine.AdFormat { get }
@objc public static var interstitialVideo: BidMachine.AdFormat { get }
}
```
}>
```objc
@interface BidMachineAdFormat (SWIFT_EXTENSION(BidMachine))
+ (BidMachineAdFormat * _Nonnull)interstitial;
+ (BidMachineAdFormat * _Nonnull)interstitialStatic;
+ (BidMachineAdFormat * _Nonnull)interstitialVideo;
@end
```
#### Available interstitial formats
| Format | Description |
| ----------------------- | -------------------------------------------------------- |
| `interstitial` | Combines both VAST (video) and MRAID (static) formats |
| `interstitialVideo` | VAST video ads only |
| `interstitialStatic` | MRAID static ads only |
### General Request
Auction request is used to set bidding parameters: The request is created with a special placement and your parameters
}>
```swift
let request = BidMachineSdk.shared.auctionRequest(placement: placement) {
$0.withUnitConfigurations([BidMachineUnitConfiguration]())
$0.appendPriceFloor(Double(10), UUID().uuidString)
}
```
}>
```objc
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement builder: ^(id _Nonnull builder) {
[builder withUnitConfigurations:@[]];
[builder appendPriceFloor:10.0 identifier:[[NSUUID UUID] UUIDString]];
}];
```
| Parameter | Type | Description |
| -------------------- | -------------------------------- | ---------------------------------- |
| `unitConfigurations` | `[BidMachineUnitConfiguration]` | Header bidding unit configurations |
| `priceFloor` | `(Double, String)` | Price floor (value and identifier) |
### Client Bidding Request
#### Bid Token
With S2S integration, you will need a **token** that you need to transfer in the request. To get a **token**, you can use method:
}>
```swift
BidMachineSdk.shared.token(placement: placement) { token in }
```
}>
```objc
[BidMachineSdk.shared tokenWithPlacement:placement completion:^(NSString *token) {
}];
```
#### Bid Payload
After completing the server-side auction, you will receive a Base64-encoded payload string, which must be passed as a parameter to the AuctionRequest.
}>
```swift
let request = BidMachineSdk.shared.auctionRequest(placement: placement) {
$0.withPayload("")
}
```
}>
```objc
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement builder: ^(id _Nonnull builder) {
[builder withPayload:@""];
}];
```
| Parameter | Type | Description |
| -------------------- | ----------------------------------- | ----------------------------------------- |
| `payload` | `String` | Custom BidMachine payload string |
## Ad Display
The ad object is used to download and display ads.
### Prepare the ad object
Request an ad using your auction request:
}>
```swift
BidMachineSdk.shared.interstitial(request: request) { [weak self] ad, error in
guard let self else { return }
self.interstitial = ad
}
```
}>
```objc
__weak typeof(self) weakSelf = self;
[[BidMachineSdk shared] interstitialWithRequest:request
completion:^(BidMachineInterstitial *ad, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
strongSelf.interstitial = ad;
}];
```
The prepared ad contains `auctionInfo` and `requestInfo`.
:::success Auction Info
The `auctionInfo` contains information about the auction, such as the winning bidder, price, and other relevant details.
The `auctionInfo` is described [here](/sdk/general/ios/advanced#auction-info).
:::
### Delegate
Subscribe to ad events:
}>
```swift
ad.delegate = self
```
}>
```objc
ad.delegate = self;
```
Implement `BidMachineAdDelegate` methods:
}>
```swift
func didLoadAd(_ ad: BidMachineAdProtocol) {}
func didFailLoadAd(_ ad: BidMachineAdProtocol, _ error: Error) {}
func didPresentAd(_ ad: BidMachineAdProtocol) {}
func didFailPresentAd(_ ad: BidMachineAdProtocol, _ error: Error) {}
func didDismissAd(_ ad: BidMachineAdProtocol) {}
func willPresentScreen(_ ad: BidMachineAdProtocol) {}
func didDismissScreen(_ ad: BidMachineAdProtocol) {}
func didUserInteraction(_ ad: BidMachineAdProtocol) {}
func didExpired(_ ad: BidMachineAdProtocol) {}
func didTrackImpression(_ ad: BidMachineAdProtocol) {}
func didTrackInteraction(_ ad: BidMachineAdProtocol) {}
func didReceiveReward(_ ad: BidMachineAdProtocol) {}
```
}>
```objc
- (void)didLoadAd:(id)ad {}
- (void)didFailLoadAd:(id)ad :(NSError *)error {}
- (void)didPresentAd:(id)ad {}
- (void)didFailPresentAd:(id)ad :(NSError *)error {}
- (void)didDismissAd:(id)ad {}
- (void)willPresentScreen:(id)ad {}
- (void)didDismissScreen:(id)ad {}
- (void)didUserInteraction:(id)ad {}
- (void)didExpired:(id)ad {}
- (void)didTrackImpression:(id)ad {}
- (void)didTrackInteraction:(id)ad {}
- (void)didReceiveReward:(id)ad {}
```
### Loading and presenting interstitial ads
:::warning Loading prerequisites
Make sure both the `delegate` and `controller` are set before loading.
:::
Example of intestitial ad loading:
}>
```swift
guard let placement = try? BidMachineSdk.shared.placement(.interstitial) else { return }
let request = BidMachineSdk.shared.auctionRequest(placement: placement)
BidMachineSdk.shared.interstitial(request: request) { [weak self] ad, error in
guard let self = self else {
return
}
self.interstitial = ad
self.interstitial.controller = self
self.interstitial.delegate = self
self.interstitial.loadAd()
}
```
}>
```objc
NSError *error = nil;
BidMachinePlacement *placement = [BidMachineSdk.shared placement:BidMachineAdFormat.interstitial
error:&error
builder:nil];
if (!placement) {
return;
}
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement
builder:nil];
__weak typeof(self) weakSelf = self;
[[BidMachineSdk shared] interstitialWithRequest:request
completion:^(BidMachineInterstitial *ad, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
strongSelf.interstitial = ad;
strongSelf.interstitial.controller = strongSelf;
strongSelf.interstitial.delegate = strongSelf;
[strongSelf.interstitial loadAd];
}];
```
Present the loaded ad:
}>
```swift
interstitial.presentAd()
```
}>
```objc
[self.interstitial presentAd];
```
---
## Native Ads(Ios)
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjcLabel from "@site/src/components/code-labels/objc";
## Ad Request
### Placement
Create placement from `AdFormat` with your parameters:
}>
```swift
let placement = try? BidMachineSdk.shared.placement(.native) {
$0.withPlacementId("")
$0.withCustomParameters([String:Any]())
}
```
}>
```objc
NSError *error = nil;
BidMachinePlacement *placement = [BidMachineSdk.shared placement:BidMachineAdFormat.native
error:&error
builder:^(id _Nonnull builder) {
[builder withPlacementId:@""];
[builder withCustomParameters:@{}];
}];
```
| Parameter | Type | Description |
| -------------------- | -------------------------------- | ---------------------------------- |
| `placementId` | `String` | Placement ID |
| `customParameters` | `[String: Any]` / `NSDictionary` | Passed directly to the server |
#### AdFormat
The placement format is defined by static properties of the `AdFormat` class:
}>
```swift
@objc(BidMachineAdFormat)
final public class AdFormat : NSObject {
@objc public static var native: BidMachine.AdFormat { get }
@objc public static var nativeIcon: BidMachine.AdFormat { get }
@objc public static var nativeImage: BidMachine.AdFormat { get }
@objc public static var nativeVideo: BidMachine.AdFormat { get }
@objc public static var nativeIconAndVideo: BidMachine.AdFormat { get }
@objc public static var nativeIconAndImage: BidMachine.AdFormat { get }
@objc public static var nativeImageAndVideo: BidMachine.AdFormat { get }
}
```
}>
```objc
@interface BidMachineAdFormat (SWIFT_EXTENSION(BidMachine))
+ (BidMachineAdFormat * _Nonnull)native;
+ (BidMachineAdFormat * _Nonnull)nativeIcon;
+ (BidMachineAdFormat * _Nonnull)nativeImage;
+ (BidMachineAdFormat * _Nonnull)nativeVideo;
+ (BidMachineAdFormat * _Nonnull)nativeIconAndVideo;
+ (BidMachineAdFormat * _Nonnull)nativeIconAndImage;
+ (BidMachineAdFormat * _Nonnull)nativeImageAndVideo;
@end
```
#### Available native formats
| Format | Description |
| ----------------------- | ---------------------------------------------------- |
| `native` | Full native ad with all assets |
| `nativeIcon` | Native ad with icon only |
| `nativeImage` | Native ad with image only |
| `nativeVideo` | Native ad with video only |
| `nativeIconAndVideo` | Native ad with icon and video |
| `nativeIconAndImage` | Native ad with icon and image |
| `nativeImageAndVideo` | Native ad with image and video |
### General Request
Auction request is used to set bidding parameters: The request is created with a special placement and your parameters
}>
```swift
let request = BidMachineSdk.shared.auctionRequest(placement: placement) {
$0.withUnitConfigurations([BidMachineUnitConfiguration]())
$0.appendPriceFloor(Double(10), UUID().uuidString)
}
```
}>
```objc
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement builder: ^(id _Nonnull builder) {
[builder withUnitConfigurations:@[]];
[builder appendPriceFloor:10.0 identifier:[[NSUUID UUID] UUIDString]];
}];
```
| Parameter | Type | Description |
| -------------------- | -------------------------------- | ---------------------------------- |
| `unitConfigurations` | `[BidMachineUnitConfiguration]` | Header bidding unit configurations |
| `priceFloor` | `(Double, String)` | Price floor (value and identifier) |
### Client Bidding Request
#### Bid Token
With S2S integration, you will need a **token** that you need to transfer in the request. To get a **token**, you can use method:
}>
```swift
BidMachineSdk.shared.token(placement: placement) { token in }
```
}>
```objc
[BidMachineSdk.shared tokenWithPlacement:placement completion:^(NSString *token) {
}];
```
#### Bid Payload
After completing the server-side auction, you will receive a Base64-encoded payload string, which must be passed as a parameter to the AuctionRequest.
}>
```swift
let request = BidMachineSdk.shared.auctionRequest(placement: placement) {
$0.withPayload("")
}
```
}>
```objc
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement builder: ^(id _Nonnull builder) {
[builder withPayload:@""];
}];
```
| Parameter | Type | Description |
| -------------------- | ----------------------------------- | ----------------------------------------- |
| `payload` | `String` | Custom BidMachine payload string |
## Ad Display
The ad object downloads and displays native ads.
### Prepare the ad object
Request an ad using your auction request:
}>
```swift
BidMachineSdk.shared.native(request: request) { [weak self] ad, error in
guard let self else { return }
self.native = ad
}
```
}>
```objc
__weak typeof(self) weakSelf = self;
[[BidMachineSdk shared] nativeWithRequest:request
completion:^(BidMachineNative *ad, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
strongSelf.native = ad;
}];
```
The loaded ad provides `auctionInfo` and `requestInfo`.
:::success Auction Info
The `auctionInfo` contains information about the auction, such as the winning bidder, price, and other relevant details.
The `auctionInfo` is described [here](/sdk/general/ios/advanced#auction-info).
:::
### Delegate
Assign the delegate to receive ad events:
}>
```swift
ad.delegate = self
```
}>
```objc
ad.delegate = self;
```
Implement `BidMachineAdDelegate` methods:
}>
```swift
func didLoadAd(_ ad: BidMachineAdProtocol) {}
func didFailLoadAd(_ ad: BidMachineAdProtocol, _ error: Error) {}
func didPresentAd(_ ad: BidMachineAdProtocol) {}
func didFailPresentAd(_ ad: BidMachineAdProtocol, _ error: Error) {}
func didDismissAd(_ ad: BidMachineAdProtocol) {}
func willPresentScreen(_ ad: BidMachineAdProtocol) {}
func didDismissScreen(_ ad: BidMachineAdProtocol) {}
func didUserInteraction(_ ad: BidMachineAdProtocol) {}
func didExpired(_ ad: BidMachineAdProtocol) {}
func didTrackImpression(_ ad: BidMachineAdProtocol) {}
func didTrackInteraction(_ ad: BidMachineAdProtocol) {}
func didReceiveReward(_ ad: BidMachineAdProtocol) {}
```
}>
```objc
- (void)didLoadAd:(id)ad {}
- (void)didFailLoadAd:(id)ad :(NSError *)error {}
- (void)didPresentAd:(id)ad {}
- (void)didFailPresentAd:(id)ad :(NSError *)error {}
- (void)didDismissAd:(id)ad {}
- (void)willPresentScreen:(id)ad {}
- (void)didDismissScreen:(id)ad {}
- (void)didUserInteraction:(id)ad {}
- (void)didExpired:(id)ad {}
- (void)didTrackImpression:(id)ad {}
- (void)didTrackInteraction:(id)ad {}
- (void)didReceiveReward:(id)ad {}
```
### Loading and presenting native ads
:::warning Loading prerequisites
Ensure both `delegate` and `controller` are set before loading.
:::
Example of native ad loading:
}>
```swift
guard let placement = try? BidMachineSdk.shared.placement(.native) else { return }
let request = BidMachineSdk.shared.auctionRequest(placement: placement)
BidMachineSdk.shared.native(request: request) { [weak self] ad, error in
guard let self = self else {
return
}
self.native = ad
self.native.controller = self
self.native.delegate = self
self.native.loadAd()
}
```
}>
```objc
NSError *error = nil;
BidMachinePlacement *placement = [BidMachineSdk.shared placement:BidMachineAdFormat.native
error:&error
builder:nil];
if (!placement) {
return;
}
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement
builder:nil];
__weak typeof(self) weakSelf = self;
[[BidMachineSdk shared] nativeWithRequest:request
completion:^(BidMachineNative *ad, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
strongSelf.native = ad;
strongSelf.native.controller = strongSelf;
strongSelf.native.delegate = strongSelf;
[strongSelf.native loadAd];
}];
```
When presenting, implement `BidMachineNativeAdRendering` to expose UI assets and register them for interaction:
}>
```swift
@objc public protocol BidMachineNativeAdRendering {
var titleLabel: UILabel? { get }
var callToActionLabel: UILabel? { get }
var descriptionLabel: UILabel? { get }
var iconView: UIImageView? { get }
var mediaContainerView: UIView? { get }
var adChoiceView: UIView? { get }
}
@objc public enum BidMachineNativeAdRenderingAssetType: Int {
case titleLabel
case callToActionLabel
case descriptionLabel
case iconView
case mediaContainerView
case adChoiceView
}
class NativeAdView: UIView, BidMachineNativeAdRendering {
var titleLabel: UILabel? { titleLab }
var callToActionLabel: UILabel? { callToActionLab }
var descriptionLabel: UILabel? { descriptionLab }
var iconView: UIImageView? { icon }
var mediaContainerView: UIView? { mediaContainer }
var adChoiceView: UIView? { nil }
@IBOutlet weak var titleLab: UILabel!
@IBOutlet weak var descriptionLab: UILabel!
@IBOutlet weak var icon: UIImageView!
@IBOutlet weak var mediaContainer: UIView!
@IBOutlet weak var callToActionLab: UILabel!
}
// Register assets and present
nativeAd.registerAssetsForInteraction([
BidMachineNativeAdRenderingAssetType.descriptionLabel.rawValue
])
let nativeAdView = NativeAdView()
try nativeAd.presentAd(in: nativeAdView, rendering: nativeAdView)
```
}>
```objc
@protocol BidMachineNativeAdRendering
@property (nonatomic, nullable) UILabel *titleLabel;
@property (nonatomic, nullable) UILabel *callToActionLabel;
@property (nonatomic, nullable) UILabel *descriptionLabel;
@property (nonatomic, nullable) UIImageView *iconView;
@property (nonatomic, nullable) UIView *mediaContainerView;
@property (nonatomic, nullable) UIView *adChoiceView;
@end
typedef NS_ENUM(NSInteger, BidMachineNativeAdRenderingAssetType) {
BidMachineNativeAdRenderingAssetTypeTitleLabel,
BidMachineNativeAdRenderingAssetTypeCallToActionLabel,
BidMachineNativeAdRenderingAssetTypeDescriptionLabel,
BidMachineNativeAdRenderingAssetTypeIconView,
BidMachineNativeAdRenderingAssetTypeMediaContainerView,
BidMachineNativeAdRenderingAssetTypeAdChoiceView
};
@interface BDMNativeAdView : UIView
@property (nonatomic, weak) IBOutlet UILabel *titleLab;
@property (nonatomic, weak) IBOutlet UILabel *descriptionLab;
@property (nonatomic, weak) IBOutlet UIImageView *icon;
@property (nonatomic, weak) IBOutlet UIView *mediaContainer;
@property (nonatomic, weak) IBOutlet UILabel *callToActionLab;
@end
@implementation BDMNativeAdView
- (UILabel *)titleLabel {
return self.titleLab;
}
- (UILabel *)callToActionLabel {
return self.callToActionLab;
}
- (UILabel *)descriptionLabel {
return self.descriptionLab;
}
- (UIImageView *)iconView {
return self.icon;
}
- (UIView *)mediaContainerView {
return self.mediaContainer;
}
-(UIView *)adChoiceView {
return nil;
}
@end
// Register assets and present
NSError *error = nil;
[nativeAd registerAssetsForInteraction:@[
@(BidMachineNativeAdRenderingAssetTypeDescriptionLabel)
]];
BDMNativeAdView *nativeAdView = [[BDMNativeAdView alloc] init];
[nativeAd presentAdInContainer:nativeAdView
rendering:nativeAdView
error:&error];
```
---
## Integration(Ios)
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import SKAdNetwork from "@site/src/components/mdx/skadnetwork";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjcLabel from "@site/src/components/code-labels/objc";
Integrate BidMachine SDK for iOS
## Integration
:::info Requirements
- iOS 13.0+ (start for `3.0.0`)
- Xcode: `14.2`, BidMachine SDK version `>= 2.4.0.0`, `<= 2.5.0`
- Xcode: `14.3.1`, BidMachine SDK version `>= 2.5.0`
- Xcode: `15.2`, BidMachine SDK version `>= 3.0.0`
- Xcode: `15.3`, BidMachine SDK version `>= 3.1.0`
:::
:::tip Recommended Integration Method
We recommend using **CocoaPods** for integration as it provides the most stable and tested integration experience.
:::
Add the following lines to your project's Podfile:
:::note
If you haven't used CocoaPods before, please read [this guide](https://guides.cocoapods.org/using/getting-started.html) first.
:::
```ruby title="Podfile"
platform :ios, '12.0'
source 'https://cdn.cocoapods.org/'
workspace 'App.xcworkspace'
use_frameworks!
target 'Target' do
pod 'BidMachine', '~> 3.8.0'
# Additionally, you can specify the type of library to use:
# pod 'BidMachine/Static', '~> 3.8.0'
# pod 'BidMachine/Dynamic', '~> 3.8.0'
project 'Project/Target.xcodeproj'
end
```
1. In Xcode, go to **File → Add Package Dependencies**
2. Enter the BidMachine SDK repository URL:
```
git@github.com:bidmachine/BidMachine-SPM.git
```
3. Select the version: `3.8.0` or specify the version range
4. Choose the target where you want to add BidMachine SDK
5. Click **Add Package**
:::warning Objective-C Linker Flag Required
When using Swift Package Manager, you must add the `-ObjC` flag to **Other Linker Flags** in your project's Build Settings:
1. Select your project in the Project Navigator
2. Select your target
3. Go to **Build Settings** tab
4. Search for "Other Linker Flags"
5. Add `-ObjC` to the list of flags
This flag is required for the SDK to function correctly.
:::
If you cannot use a dependency manager, you can integrate the SDK manually.
**1. Download the frameworks**
- BidMachine SDK: `https://bidmachine-ios.s3.amazonaws.com/BidMachine//pod/BidMachine.zip` (e.g. `3.8.0`). The archive contains both `release/Static` and `release/Dynamic` variants of `BidMachine.xcframework` — pick one.
- OM SDK (required dependency): [https://bidmachine-ios.s3.amazonaws.com/OMSDK_Appodeal/1.6.3/package/OMSDK_Appodeal.xcframework.zip](https://bidmachine-ios.s3.amazonaws.com/OMSDK_Appodeal/1.6.3/package/OMSDK_Appodeal.xcframework.zip)
**2. Add the frameworks to your project**
Drag `BidMachine.xcframework` and `OMSDK_Appodeal.xcframework` into your Xcode project (check **Copy items if needed**), then in your target's **General → Frameworks, Libraries, and Embedded Content**:
- **Dynamic** variant: set both frameworks to **Embed & Sign**
- **Static** variant: set both frameworks to **Do Not Embed**
**3. Static variant only — link system frameworks and libraries**
Add the following to your target (**Build Phases → Link Binary With Libraries**):
`AdSupport`, `AppTrackingTransparency`, `AudioToolbox`, `AVFoundation`, `AVKit`, `CFNetwork`, `CoreGraphics`, `CoreImage`, `CoreLocation`, `CoreMedia`, `CoreTelephony`, `ImageIO`, `QuartzCore`, `SafariServices`, `Security`, `StoreKit`, `SystemConfiguration`, `UIKit`, `WebKit` and the libraries `libz.tbd`, `libsqlite3.tbd`, `libxml2.tbd`.
**4. Static variant only — add the privacy manifest**
Copy `PrivacyInfo.xcprivacy` from `BidMachine.xcframework/ios-arm64/` into your app target (required for App Store submission). The dynamic variant ships it inside the framework bundle automatically.
**5. Add the `-ObjC` linker flag**
:::warning Objective-C Linker Flag Required
You must add the `-ObjC` flag to **Other Linker Flags** in your project's Build Settings:
1. Select your project in the Project Navigator
2. Select your target
3. Go to **Build Settings** tab
4. Search for "Other Linker Flags"
5. Add `-ObjC` to the list of flags
This flag is required for the SDK to function correctly.
:::
:::note
When updating the SDK manually, remember to also update `OMSDK_Appodeal.xcframework` if the required version changes — check the [changelog](/docs/sdk/general/ios/changelog).
:::
:::warning Unity Integration
If you're integrating BidMachine SDK in a Unity project, you must disable static linking to avoid build errors:
**Solution:**
Disable static linking in your Unity project:
```
Assets → External Dependency Manager → iOS Resolver → Settings → Uncheck "Link frameworks statically"
```
This will switch the Podfile to use `use_frameworks!` (dynamic linking) and the build should complete successfully.
:::
### Network security configuration
Add this code to the `Info.plist` file:
```xml title="Info.plist"
NSAppTransportSecurityNSAllowsArbitraryLoads
```
### App Tracking Transparency
BidMachine SDK supports App Tracking Transparency (ATT) framework.
If you’re unfamiliar with it, we recommend reviewing
[Apple’s documentation on ATT](https://developer.apple.com/documentation/apptrackingtransparency) as part of this process.
### Privacy Manifest
:::success Support for Privacy Manifest
BidMachine SDK 2.6.1+ supports a Privacy Manifest file to comply with Apple's Privacy Manifest Framework.
:::
**Required Reasoning API**
| Required Reasoning APIs | API Type | Reason |
| ----------------------- | ------------------------------------------- | ------ |
| File Timestamp APIs | `NSPrivacyAccessedAPICategoryFileTimestamp` | C617.1 |
| Disk Space APIs | `NSPrivacyAccessedAPICategoryDiskSpace` | E174.1 |
| User Defaults APIs | `NSPrivacyAccessedAPICategoryUserDefaults` | CA92.1 |
### SKAdNetwork Support
The SDK support [SKAdNetwork](https://developer.apple.com/documentation/storekit/skadnetwork/) to allow ad networks to attribute app installs even when IDFA is unavailable.
To enable this functionality, you need to add the SKAdNetworkItems key to your Info.plist file.
1. Select Info.plist in the Project navigator in Xcode
2. Right-click on `Info.plist` file → Open as → Source Code
3. Copy the SKAdNetworkItems from below and paste it into your `Info.plist` file
There is SKAdNetworks IDs in `Info.plist` format
### AdAttributionKit Support
The SDK supports [AdAttributionKit](https://developer.apple.com/documentation/adattributionkit)
for app ad campaigns on the App Store and alternative marketplaces.
To enable this functionality, you need to add the `AdAttributionItems` key to your Info.plist file.
:::tip AdAttributionItems
`AdAttributionItems` remains same as `SKAdNetworkItems`
:::
:::note AdNetworkIdentifiers
The SDK reads AdAttributionKit network identifiers from a **top-level** `AdNetworkIdentifiers`
array of strings, and forwards them to buyers in the bid request. If you only declare
`AdAttributionItems`, that array is sent empty. Declare both:
```xml title="Info.plist"
AdNetworkIdentifierswg4vff78zm.skadnetwork
```
:::
## Initialization
To initialize the SDK - you need to call the initialization method with your source id
}>
```swift
BidMachineSdk.shared.initializeSdk("YOUR_SOURCE_ID")
```
}>
```objc
[BidMachineSdk.shared initializeSdk:@"YOUR_SOURCE_ID"];
```
:::tip Source ID
You can find your `SOURCE_ID` in your [BidMachine Dashboard](https://dashboard.bidmachine.io).
:::
### SDK Status
Sdk status can be checked via method
}>
```swift
_ = BidMachineSdk.shared.isInitialized
```
}>
```objc
[BidMachineSdk.shared isInitialized];
```
### Global Getters
You can get the SDK version, name, partner name and partner version using the following methods:
}>
```swift
_ = BidMachineSdk.sdkVersion
_ = BidMachineSdk.sdkName
_ = BidMachineSdk.partnerName
_ = BidMachineSdk.partnerVersion
```
}>
```objc
NSString *version = [BidMachineSdk sdkVersion];
NSString *name = [BidMachineSdk sdkName];
NSString *partner = [BidMachineSdk partnerName];
NSString *partnerV = [BidMachineSdk partnerVersion];
```
---
## Data Privacy(Ios)
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjcLabel from "@site/src/components/code-labels/objc";
## GDPR
Effective May 25, 2019, the European Union's General Data Protection Regulation (GDPR) has been in force.
To meet its requirements, developers can choose from these options.
### Consent Management Platform (CMP)
A Consent Management Platform (CMP) is a tool that helps developers collect, manage,
and store user consent for data processing activities.
As a publisher, you should integrate a Consent Management Platform (CMP)
that adheres to [IAB TCF v2](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/Consent%20string%20and%20vendor%20list%20formats%20v1.1%20Final.md).
Don't load any ads until the CMP has confirmed the user's consent status.
The BidMachine SDK will then consume the TCF v2 consent string supplied by your CMP.
Please note that BidMachine does not audit CMPs for full TCF compliance or adherence to applicable privacy laws.
:::note
Regulation state is resolved using IAB TCF v2 data and publisher-provided regulation settings.
IAB TCF v1 data is not used when resolving the SDK regulation result.
:::
### Manually
If you prefer not to use a CMP, you can manually collect user consent and pass it to the BidMachine SDK.
To set subject to GDPR, use the following method:
}>
```swift
import BidMachine
BidMachineSdk.shared.withGDPRZone(true)
```
}>
```objc
#import
[BidMachineSdk.shared withGDPRZone:YES];
```
To indicate whether the user has given consent for personalized data processing, use the following method:
}>
```swift
import BidMachine
BidMachineSdk.shared.withGDPRConsent(true)
```
}>
```objc
#import
[BidMachineSdk.shared withGDPRConsent:YES];
```
## CCPA
Effective July 1, 2020, the California Consumer Privacy Act (CCPA) comes into force,
To pass CCPA U.S. Privacy String to BidMachine, use: `withUSPrivacyString`.
}>
```swift
import BidMachine
BidMachineSdk.shared.withUSPrivacyString("")
```
}>
```objc
#import
[BidMachineSdk.shared withUSPrivacyString:@""];
```
Also, SDK automatically retrieves CCPA U.S. Privacy String from SharedPreference.
If you would like to pass CCPA U.S. Privacy String according to IAB standards,
please add it in SharedPreference. More information [here](https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/master/CCPA/US%20Privacy%20String.md)
and [here](https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/master/CCPA/USP%20API.md#in-app-support).
## COPPA
To help ensure compliance with COPPA, you must indicate whether a user falls within an age-restricted category.
To pass COPPA to BidMachine, use:
}>
```swift
import BidMachine
BidMachineSdk.shared.withCOPPA(true)
```
}>
```objc
#import
[BidMachineSdk.shared withCOPPA:YES];
```
## Non-Personalized Ads
Available since SDK `3.7.0`. Publishers use this flag to request non-personalized ads and to limit the data BidMachine collects and shares with demand partners.
This is relevant in several scenarios:
- **Age-restricted users in the US** — US state laws (CCPA/CPRA in California, and similar laws in Virginia, Colorado, Connecticut, and others) prohibit selling or sharing personal data of users under 16 without opt-in consent. For users under 13, COPPA applies stricter rules. Publishers should use this flag alongside `withCOPPA(_:)` when they cannot determine the exact age but targeting must be limited.
- **Users who declined personalized advertising** — when a user opts out of personalized ads through the publisher's consent flow but is not subject to a specific regulation covered by the other APIs.
- **General opt-out** — as a catch-all to suppress targeting signals when none of the more specific privacy flags apply.
When set to `true`, BidMachine requests non-personalized ads only.
}>
```swift
import BidMachine
BidMachineSdk.shared.withNonPersonalized(true)
```
}>
```objc
#import
[BidMachineSdk.shared withNonPersonalized:YES];
```
## GPP
The Global Privacy Platform (GPP) is a unified protocol that helps advertisers, publishers,
and technology providers in digital advertising comply with evolving regulations worldwide.
By centralizing the transmission of privacy, consent, and consumer-choice signals from websites and apps to ad-tech partners,
it simplifies compliance efforts.
To pass GPP to BidMachine, there is 2 options:
### Using CMP API Specification
If you are using a Consent Management Platform (CMP) that supports the IAB's CMP API Specification,
BidMachine SDK can automatically retrieve GPP data from the `SharedPreferences` or `UserDefaults`.
### Manually
BidMachine SDK provides a recommended method to pass GPP data directly.
This method allows you to set the GPP string and associated IDs in a straightforward manner.
}>
```swift
import BidMachine
BidMachineSdk.shared.withGPP("", [])
```
}>
```objc
#import
[BidMachineSdk.shared withGPP:@"" :@[]];
```
---
## Rewarded Ads(Ios)
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjcLabel from "@site/src/components/code-labels/objc";
## Ad Request
### Placement
Create placement from `AdFormat` with your parameters:
}>
```swift
let placement = try? BidMachineSdk.shared.placement(.rewarded) {
$0.withPlacementId("")
$0.withCustomParameters([String:Any]())
}
```
}>
```objc
NSError *error = nil;
BidMachinePlacement *placement = [BidMachineSdk.shared placement:BidMachineAdFormat.rewarded
error:&error
builder:^(id _Nonnull builder) {
[builder withPlacementId:@""];
[builder withCustomParameters:@{}];
}];
```
| Parameter | Type | Description |
| -------------------- | -------------------------------- | ---------------------------------- |
| `placementId` | `String` | Placement ID |
| `customParameters` | `[String: Any]` / `NSDictionary` | Passed directly to the server |
#### AdFormat
The placement format is defined by static properties of the `AdFormat` class:
}>
```swift
@objc(BidMachineAdFormat)
final public class AdFormat : NSObject {
@objc public static var rewarded: BidMachine.AdFormat { get }
@objc public static var rewardedStatic: BidMachine.AdFormat { get }
@objc public static var rewardedVideo: BidMachine.AdFormat { get }
}
```
}>
```objc
@interface BidMachineAdFormat (SWIFT_EXTENSION(BidMachine))
+ (BidMachineAdFormat * _Nonnull)rewarded;
+ (BidMachineAdFormat * _Nonnull)rewardedStatic;
+ (BidMachineAdFormat * _Nonnull)rewardedVideo;
@end
```
#### Available rewarded formats
| Format | Description |
| ------------------- | -------------------------------------------------------- |
| `rewarded` | Combines both VAST (video) and MRAID (static) formats |
| `rewardedVideo` | VAST video ads only |
| `rewardedStatic` | MRAID static ads only |
### General Request
Auction request is used to set bidding parameters: The request is created with a special placement and your parameters
}>
```swift
let request = BidMachineSdk.shared.auctionRequest(placement: placement) {
$0.withUnitConfigurations([BidMachineUnitConfiguration]())
$0.appendPriceFloor(Double(10), UUID().uuidString)
}
```
}>
```objc
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement builder: ^(id _Nonnull builder) {
[builder withUnitConfigurations:@[]];
[builder appendPriceFloor:10.0 identifier:[[NSUUID UUID] UUIDString]];
}];
```
| Parameter | Type | Description |
| -------------------- | -------------------------------- | ---------------------------------- |
| `unitConfigurations` | `[BidMachineUnitConfiguration]` | Header bidding unit configurations |
| `priceFloor` | `(Double, String)` | Price floor (value and identifier) |
### Client Bidding Request
#### Bid Token
With S2S integration, you will need a **token** that you need to transfer in the request. To get a **token**, you can use method:
}>
```swift
BidMachineSdk.shared.token(placement: placement) { token in }
```
}>
```objc
[BidMachineSdk.shared tokenWithPlacement:placement completion:^(NSString *token) {
}];
```
#### Bid Payload
After completing the server-side auction, you will receive a Base64-encoded payload string, which must be passed as a parameter to the AuctionRequest.
}>
```swift
let request = BidMachineSdk.shared.auctionRequest(placement: placement) {
$0.withPayload("")
}
```
}>
```objc
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement builder: ^(id _Nonnull builder) {
[builder withPayload:@""];
}];
```
| Parameter | Type | Description |
| -------------------- | ----------------------------------- | ----------------------------------------- |
| `payload` | `String` | Custom BidMachine payload string |
## Ad Display
The ad object handles downloading and displaying ads.
### Prepare the ad object
Request an ad using your auction request:
}>
```swift
BidMachineSdk.shared.rewarded(request: request) { [weak self] ad, error in
guard let self else { return }
self.rewarded = ad
}
```
}>
```objc
__weak typeof(self) weakSelf = self;
[[BidMachineSdk shared] rewardedWithRequest:request
completion:^(BidMachineRewarded *ad, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
strongSelf.rewarded = ad;
}];
```
The loaded ad provides `auctionInfo` and `requestInfo`.
:::success Auction Info
The `auctionInfo` contains information about the auction, such as the winning bidder, price, and other relevant details.
The `auctionInfo` is described [here](/sdk/general/ios/advanced#auction-info).
:::
### Delegate
Assign the delegate to receive ad events:
}>
```swift
ad.delegate = self
```
}>
```objc
ad.delegate = self;
```
Implement `BidMachineAdDelegate` methods:
}>
```swift
func didLoadAd(_ ad: BidMachineAdProtocol) {}
func didFailLoadAd(_ ad: BidMachineAdProtocol, _ error: Error) {}
func didPresentAd(_ ad: BidMachineAdProtocol) {}
func didFailPresentAd(_ ad: BidMachineAdProtocol, _ error: Error) {}
func didDismissAd(_ ad: BidMachineAdProtocol) {}
func willPresentScreen(_ ad: BidMachineAdProtocol) {}
func didDismissScreen(_ ad: BidMachineAdProtocol) {}
func didUserInteraction(_ ad: BidMachineAdProtocol) {}
func didExpired(_ ad: BidMachineAdProtocol) {}
func didTrackImpression(_ ad: BidMachineAdProtocol) {}
func didTrackInteraction(_ ad: BidMachineAdProtocol) {}
func didReceiveReward(_ ad: BidMachineAdProtocol) {}
```
}>
```objc
- (void)didLoadAd:(id)ad {}
- (void)didFailLoadAd:(id)ad :(NSError *)error {}
- (void)didPresentAd:(id)ad {}
- (void)didFailPresentAd:(id)ad :(NSError *)error {}
- (void)didDismissAd:(id)ad {}
- (void)willPresentScreen:(id)ad {}
- (void)didDismissScreen:(id)ad {}
- (void)didUserInteraction:(id)ad {}
- (void)didExpired:(id)ad {}
- (void)didTrackImpression:(id)ad {}
- (void)didTrackInteraction:(id)ad {}
- (void)didReceiveReward:(id)ad {}
```
### Loading and presenting rewarded ads
:::warning Loading prerequisites
Make sure both the `delegate` and `controller` are set before loading.
:::
Example of rewarded ad loading:
}>
```swift
guard let placement = try? BidMachineSdk.shared.placement(.rewarded) else { return }
let request = BidMachineSdk.shared.auctionRequest(placement: placement)
BidMachineSdk.shared.rewarded(request: request) { [weak self] ad, error in
guard let self = self else {
return
}
self.rewarded = ad
self.rewarded.controller = self
self.rewarded.delegate = self
self.rewarded.loadAd()
}
```
}>
```objc
NSError *error = nil;
BidMachinePlacement *placement = [BidMachineSdk.shared placement:BidMachineAdFormat.rewarded
error:&error
builder:nil];
if (!placement) {
return;
}
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement
builder:nil];
__weak typeof(self) weakSelf = self;
[[BidMachineSdk shared] rewardedWithRequest:request
completion:^(BidMachineRewarded *ad, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
strongSelf.rewarded = ad;
strongSelf.rewarded.controller = strongSelf;
strongSelf.rewarded.delegate = strongSelf;
[strongSelf.rewarded loadAd];
}];
```
Present the ad:
}>
```swift
rewarded.presentAd()
```
}>
```objc
[self.rewarded presentAd];
```
---
## Header-Bidding
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjcLabel from "@site/src/components/code-labels/objc";
## Integration
:::info Requirements
- iOS 13.0+ (start for `3.0.0`)
- Xcode: `14.2`, BidMachine SDK version `>= 2.4.0.0`, `<= 2.5.0`
- Xcode: `14.3.1`, BidMachine SDK version `>= 2.5.0`
- Xcode: `15.2`, BidMachine SDK version `>= 3.0.0`
- Xcode: `15.3`, BidMachine SDK version `>= 3.1.0`
:::
### CocoaPods
Adapters are distributed as sub-specs with external dependencies. Add following lines into your Podfile:
:::note
If you haven't used CocoaPods before, please read this guide first.
:::
```ruby
platform :ios, '13.0'
source 'https://github.com/appodeal/CocoaPods.git'
source 'https://cdn.cocoapods.org/'
workspace 'YourApp.xcworkspace'
use_frameworks!
target 'YourTarget' do
project 'YourProject/YourTarget.xcodeproj'
pod "BidMachine", "~> 3.3.0.0"
pod "BidMachineAdColonyAdapter", "~> 3.3.0.0"
pod "BidMachineAmazonAdapter", "~> 3.3.0.0"
pod "BidMachineCriteoAdapter","~> 3.3.0.0"
pod "BidMachineMetaAudienceAdapter", "~> 3.3.0.0"
pod "BidMachineMyTargetAdapter", "~> 3.3.0.0"
pod "BidMachineSmaatoAdapter", "~> 3.3.0.0"
pod "BidMachineTapjoyAdapter", "~> 3.3.0.0"
pod "BidMachineVungleAdapter", "~> 3.3.0.0"
pod "BidMachinePangleAdapter", "~> 3.3.0.0"
pod "BidMachineMintegralAdapter", "~> 3.3.0.0"
end
```
## Registration
To register the Header Bidding Network - you need to call the registration method with network configuration.
}>
```swift
let config = BidMachineNetworkConfiguraton("NETWORK_NAME", // NETWORK_NAME
[String : Any](), // REQUIRED NETWORK INIT PARAMS
[String : Any]()) // OPTIONAL ANY EXTRAS PARAMS
BidMachineSdk.shared.registerNetworks([config])
```
}>
```objc
BidMachineNetworkConfiguraton *config = [[BidMachineNetworkConfiguraton alloc]
initWithName:@"NETWORK_NAME" // NETWORK_NAME
params:@{} // REQUIRED NETWORK INIT PARAMS
extras:@{}]; // OPTIONAL ANY EXTRAS PARAMS
[BidMachineSdk.shared registerNetworks:@[config]];
```
### Request with Header Bidding Networks
In order for header bidding networks to participate in bidding, you need to add to the request all the bidding ad units with which you want to auction.
}>
```swift
let unitConfig = BidMachineUnitConfiguration("name", // NETWORK_NAME
.banner320x50, // AD UNIT TYPE
[String : Any](), // REQUIRED NETWORK UNIT PARAMS
[String : Any]()) // OPTIONAL ANY EXTRAS PARAMS
let placement = try? BidMachineSdk.shared.placement(.banner320x50)
let request = BidMachineSdk.shared.auctionRequest(placement: placement) {
$0.withUnitConfigurations([unitConfig])
}
```
}>
```objectivec
BidMachineUnitConfiguration *unitConfig = [[BidMachineUnitConfiguration alloc]
initWithName:@"name" // NETWORK_NAME
format:BidMachinePlacementFormatBanner320x50 // AD UNIT TYPE
params:@{} // REQUIRED NETWORK UNIT PARAMS
extras:@{}]; // OPTIONAL ANY EXTRAS PARAMS
NSError *error = nil;
BidMachinePlacement *placement = [BidMachineSdk.shared placement:BidMachineAdFormat.banner320x50
error:&error
builder:nil];
if (!placement) {
// handle error
return;
}
BidMachineAuctionRequest *request = [[BidMachineSdk shared] auctionRequestWithPlacement:placement
builder:^(id builder) {
[builder withUnitConfigurations:@[unitConfig]];
}];
```
### Test mode + Logging mode
}>
```swift
BidMachineSdk.shared
.withTestMode(true)
.withLoggingMode(true)
```
}>
```objectivec
[BidMachineSdk.shared withTestMode:YES];
[BidMachineSdk.shared withLoggingMode:YES];
```
## Bidding Networks Params
### AdColony
#### Network Name: `adcolony`
| Initialization Parameters | Type |
| :------------------------ | :----- |
| app_id | String |
| Ad Unit Parameters | Type |
| :----------------- | :----- |
| zone_id | String |
### Amazon
#### Network Name: `amazon`
| Initialization Parameters | Type |
| :------------------------ | :----- |
| app_key | String |
| Ad Unit Parameters | Type |
| :----------------- | :----- |
| slot_uuid | String |
### Criteo
#### Network Name: `criteo`
| Initialization Parameters | Type |
| :------------------------ | :----- |
| publisher_id | String |
| Ad Unit Parameters | Type |
| :-------------------- | :------------------------------------- |
| ad_unit_id | String |
| orientation(optional) | String (**portrait** or **landscape**) |
### Meta
#### Network Name: `meta_audience`
| Initialization Parameters | Type |
| :------------------------ | :-------------- |
| app_id | String |
| placement_ids | Array of String |
| Ad Unit Parameters | Type |
| :----------------- | :----- |
| meta_key | String |
### MyTarget
#### Network Name: `my_target`
| Initialization Parameters |
| :------------------------------------------------------ |
| does not contain required parameters for initialization |
| Ad Unit Parameters | Type |
| :----------------- | :----- |
| slot_id | String |
### Pangle
#### Network Name: `pangle_sdk`
| Initialization Parameters | Type |
| :------------------------ | :----- |
| app_id | String |
| Ad Unit Parameters | Type |
| :----------------- | :----- |
| slot_id | String |
### Smaato
#### Network Name: `smaato`
| Initialization Parameters | Type |
| :------------------------ | :----- |
| publisher_id | String |
| Ad Unit Parameters | Type |
| :----------------- | :----- |
| ad_space_id | String |
### Tapjoy
#### Network Name: `tapjoy`
| Initialization Parameters | Type |
| :------------------------ | :----- |
| sdk_key | String |
| Ad Unit Parameters | Type |
| :----------------- | :----- |
| placement_name | String |
### Vungle
#### Network Name: `vungle`
| Initialization Parameters | Type |
| :------------------------ | :----- |
| app_id | String |
| Ad Unit Parameters | Type |
| :----------------- | :----- |
| placement_id | String |
---
## Leveraging RampID
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjcLabel from "@site/src/components/code-labels/objc";
By providing **LiveRamp envelope** to BidMachine, publishers can boost monetization while staying compliant with privacy standards. BidMachine collaborates with **LiveRamp** and uses the LiveRamp Authenticated Traffic Solution (ATS) API.
For more information on LiveRamp's Authenticated Traffic Solution and how it works, refer to this [page](https://developers.liveramp.com/authenticatedtraffic-api/docs/what-is-ats)
### How to submit data:
Note that BidMachine only accept **LiveRamp** envelopes.
Learn more about the identity envelope [link](https://developers.liveramp.com/rampid-api/docs/the-identity-envelope-decryption-endpoint-copy)
To participate, please follow these steps:
1. Establish a contract and integration with **LiveRamp**.
2. Currently, the **BidMachine SDK** supports passing a publishe's **LiveRamp envelope** as an external ID within the SDK. So you need to generate envelope using ATS and pass it to BidMachine SDK.
### Passing in an external LiveRamp envelope value to BidMachine SDK:
}>
```java
public String exampleEnvelopeString = "AY3SYJlFDI1RqsMv9gZOjOab6hGuwWKmbE4K70Z-Zex27DD6M9U0Jg";
public TargetingParams createTargetingParams(String exampleEnvelopeString) {
List externalUserIdList = new ArrayList<>();
externalUserIdList.add(new ExternalUserId("liveramp.com", exampleEnvelopeString));
TargetingParams targetingParams = new TargetingParams();
targetingParams.setExternalUserIds(externalUserIdList);
return targetingParams;
}
```
}>
```kotlin
val exampleEnvelopeString = "AY3SYJlFDI1RqsMv9gZOjOab6hGuwWKmbE4K70Z-Zex27DD6M9U0Jg"
fun createTargetingParams(exampleEnvelopeString: String): TargetingParams {
return TargetingParams().apply {
setExternalUserIds(listOf(ExternalUserId("liveramp.com", exampleEnvelopeString)))
}
}
```
}>
```swift
import BidMachine
let exampleEnvelopeString = "AY3SYJlFDI1RqsMv9gZOjOab6hGuwWKmbE4K70Z-Zex27DD6M9U0Jg"
BidMachineSdk.shared.targetingInfo.populate {
$0.appendExternalId("liveramp.com", exampleEnvelopeString)
}
```
}>
```objc
#import
NSString* exampleEnvelopeString = @"AY3SYJlFDI1RqsMv9gZOjOab6hGuwWKmbE4K70Z-Zex27DD6M9U0Jg";
[BidMachineSdk.shared.targetingInfo populate:^(id builder) {
[builder appendExternalId:@"liveramp.com" :exampleEnvelopeString];
}];
```
---
## In-House Mediation
## How to add BidMachine to Publisher Direct Bidding (PDB) auction within In-House mediation
BidMachine could be easily integrated into the PDB auction.
Documentation on how to integrate BidMachine SDK can be found [here](/sdk/overview).
Step-by-step integration is the following:
- At the start of the application, BidMachine should be initialized according to the doc (section: Initialisation)
- An app requests a mediation ad and fetches the price of a loaded ad
- An app requests an ad from BidMachine with the price that was returned by mediation plus some added amount (we recommend using 0.01$), other PDB partners should be requested with the same price
- If BidMachine wins the PDB auction - the publisher loads its creative and uses it for impressions later
:::warning Ad Price
Your In-House mediation module must have the ability to return the price of the loaded ads.
:::
If there are multiple demand sources in the PDB auction, the publisher should notify BidMachine with win and loss notification.
Publisher shall populate the auction winning price via a loss notice URL according to this documentation: [iOS](/sdk/general/ios/advanced#winloss-notifications), [Android](/sdk/general/android/advanced#winloss-notifications).
The publisher should set up an interval for the BidMachine request in PDB not less than:
- **10 seconds** for Banner/MREC
- **15 seconds** for Interstitial
- **30 seconds** for Rewarded Video
### Integration
You need to add BidMachine SDK to your project:
```groovy Android (build.gradle)
repositories {
maven {
url "https://artifactory.bidmachine.io/bidmachine"
}
}
dependencies {
implementation "io.bidmachine:ads:3.0.0"
}
```
```ruby iOS (CocoPods)
pod 'BidMachine', '~> 3.0.0'
```
> ❗️ Please note that all subsequent examples will use **pseudocode** as the API of the Mediation SDK.
For unity integration click Assets - Import package
### Initialization
BidMachine SDK should be properly configured and initialized **before** your mediation module initializes.
```java Android (Java)
// 1. Prepare BidMachine environment - GDPR, CCPA, GPP, Coppa, test mode, etc...
// 2. Initializing BidMachine
BidMachine.initialize(context, "");
// 3. Prepare Mediation environment - GDPR, CCPA, Coppa, etc...
// 4. Initializing In-House mediation
Mediation.initilize();
```
```swift iOS (Swift)
// 1. Prepare BidMachine environment - GDPR, CCPA, GPP, Coppa, test mode, etc...
/**
BidMachineSdk.shared.populate {
$0.withLoggingMode(true)
}
*/
// 2. Initializing BidMachine
BidMachineSdk.shared.initializeSdk("")
// 3. Prepare Mediation environment - GDPR, CCPA, Coppa, etc...
// 4. Initializing In-House mediation
Mediation.initilize()
```
```{csharp}
// 1. Prepare BidMachine environment - GDPR, CCPA, GPP, Coppa, test mode, etc...
// 2. Initializing BidMachine
BidMachine.Initialize("");
// 3. Prepare Mediation environment - GDPR, CCPA, Coppa, etc...
// 4. Initializing In-House mediation
Mediation.initilize();
```
### Interstitial
To implement PDB auction over Interstitial Ad you need to follow the next steps:
1. Load a Mediation Interstitial
```java Android (Java)
mediationInterstitialAd = new MediationInterstitial(context)
.setListener(new MediationInterstitialListener())
.load();
```
```swift iOS (Swift)
let mediationInterstitialAd = MediationInterstitial()
mediationInterstitialAd.delegate = self
mediationInterstitialAd.loadAd
```
```{csharp}
mediationInterstitialAd = new MediationInterstitial(context)
.setListener(new MediationInterstitialListener())
.load();
```
2. Handle loading callback methods from Mediation
```java Android (Java)
@Override
public void onInterstitialReady(MediationInterstitial interstitial) {
loadBidMachineInterstitial(interstitial.responseInfo);
}
@Override
public void onInterstitialLoadFailed(MediationInterstitial interstitial, MediationError error) {
loadBidMachineInterstitial(null);
}
```
```swift iOS (Swift)
func interstitialDidLoad(interstitial: MediationInterstitial) {
loadBidMachineInterstitial(interstitial.responseInfo)
}
func interstitialDidFailToLoadWithError(interstitial: MediationInterstitial, error: any Error) {
loadBidMachineInterstitial(nil)
}
```
```{csharp}
public void InterstitialOnAdReady(MediationInterstitial interstitial)
{
LoadBidMachineInterstitialPDB(interstitial.responseInfo);
}
public void InterstitialOnAdLoadFailed(IronSourceError ironSourceError)
{
LoadBidMachineInterstitialAd();
}
```
3. Load BidMachine Interstitial
If Mediation Interstitial has been loaded, you will need to add `price floor` parameter to the BidMachine request. Otherwise don't pass anything, BidMachine will use the default value of **0.01$**.
`price floor` is an ad `CPM` value by adding `0.01$`. If your Mediation operates with revenue per impression you need to transform it to `CPM` by multiplying the revenue by **1000** and adding `0.01$`. `priceFloor = adRevenue * 1000 + 0.01`
```java Android (Java)
// Get revenue from mediation and convert it to CPM
mediationPrice = responseInfo.getRevenue() * 1000
// Calculate price floor
// Reponse info provides revenue per impression
double priceFloor = mediationPrice + 0.01;
// Reponse info provides CPM
// double priceFloor = responseInfo.getCPM() + 0.01;
// Make parameters object
PriceFloorParams priceFloorParams = new PriceFloorParams()
.addPriceFloor(priceFloor);
// Set object to the request
requestBuilder.setPriceFloorParams(priceFloorParams);
```
```swift iOS (Swift)
// mediationPrice default value is 0
// Calculate price floor
// Reponse info provides revenue per impression
mediationPrice = responseInfo.revenue.doubleValue * 1000
let priceFloor = mediationPrice + 0.01
// Reponse info provides CPM
// let priceFloor = responseInfo.cpm.doubleValue + 0.01
// Create request configuration
let configuration = try BidMachineSdk.shared.requestConfiguration(.interstitial)
// Set price floor to the request configuration
// Name parameter is optional and can be any string
configuration.populate {
$0.appendPriceFloor(priceFloor, "Placement-\(configuration.placement.name)")
}
```
```{csharp}
// Calculate price floor
double revenue = adInfo.revenue ?? 0.0;
// Make parameters object
priceFloorParams = new PriceFloorParams();
priceFloorParams.AddPriceFloor("pdb_ironsource_inter", revenue*1000+0.01);
// Set object to the request
interstitialRequest = new InterstitialRequest.Builder()
.SetPriceFloorParams(priceFloorParams)
.Build();
```
4. Add `mediation_mode` as `pdb` or any other value that identifies the PDB auction to request custom parameters. It will allow to split data in dashboard
```java Android (Java)
CustomParams customParams = new CustomParams()
.addParam("mediation_mode", "pdb_${PUBID}");
requestBuilder.setCustomParams(customParams);
```
```swift iOS (Swift)
configuration.populate {
$0.withCustomParameters(["mediation_mode": "pdb_${PUBID}"])
}
```
```{csharp}
public CustomParams customParams;
customParams = new CustomParams();
customParams.AddParam("mediation_mode", "pdb_is");
```
5. Load BidMachine Interstitial
```java Android (Java)
interstitialAd = new InterstitialAd(context)
.setListener(new BidMachineInterstitialListener())
.load(requestBuilder.build());
```
```swift iOS (Swift)
BidMachineSdk.shared.interstitial(configuration) { [weak self] interstitial, error in
guard let interstitial = interstitial else { return }
interstitial.controller = self
interstitial.loadAd()
}
```
```{csharp}
interstitialAd = new InterstitialAd();
interstitialAd.SetListener(interstitialListener);
interstitialAd.Load(interstitialRequest);
```
6. Show ad.
At the impression opportunity moment, you need to check if the BidMachine ad is ready or not.
If BidMachine Interstitial wasn't loaded successfully you need to present Mediation Interstitial
```java Android (Java)
if (interstitialAd != null
&& interstitialAd.canShow()
&& interstitialAd.getAuctionResult() != null
&& interstitialAd.getAuctionResult().getPrice() >= mediationPrice) {
interstitialAd.show();
} else {
mediationInterstitial.show();
}
```
```swift iOS (Swift)
if let interstitial = interstitial, interstitial.canShow, interstitial.auctionInfo.price >= mediationPrice {
interstitial.presentAd()
} else {
mediationInterstitial.present(from: self)
}
```
```{csharp}
if (interstitialAd.CanShow() && bidmachineInterPrice > MediationInterstitial)
{
interstitialAd.Show();
}
else
{
MediationInterstitial.show();
}
```
7. **Optional**. For the PDB auction you might want to implement loading timeout logic. We recommend adding at least **15 seconds** loading timeout.
### Rewarded Ad
To implement PDB auction over Rewarded Ad you need to follow the next steps:
1. Load a Mediation Rewarded Ad
```java Android (Java)
mediationRewardedAd = new MediationRewardedAd(context)
.setListener(new MediationRewardedAdListener())
.load();
```
```swift iOS (Swift)
let mediationRewardedAd = MediationRewardedAd()
mediationRewardedAd.delegate = self
mediationRewardedAd.loadAd
```
```{csharp}
mediationRewardedAd = new MediationRewardedAd(context)
.setListener(new MediationRewardedAdListener())
.load();
```
2. Handle loading callback methods from Mediation
```java Android (Java)
@Override
public void onRewardedAdReady(MediationRewardedAd rewardedAd) {
loadBidMachineRewardedAd(rewardedAd.responseInfo);
}
@Override
public void onRewardedAdLoadFailed(MediationRewardedAd interstitial, MediationError error) {
loadBidMachineRewardedAd(null);
}
```
```swift iOS (Swift)
func rewardedAdDidLoad(rewardedAd: MediationRewardedAd) {
loadBidMachineRewardedAd(interstitial.responseInfo)
}
func rewardedAdDidFailToLoadWithError(rewardedAd: MediationRewardedAd, error: any Error) {
loadBidMachineRewardedAd(nil)
}
```
```{csharp}
public void RewardedOnAdReadyEvent(MediationRewardedAd rewardedAd)
{
LoadBidMachineRewardedPDB(rewardedAd.responseInfo);
}
public void RewardedOnAdLoadFailed(IronSourceError ironSourceError)
{
LoadBidMachinerewardedAd();
}
```
3. Load BidMachine Rewarded Ad
If Mediation Rewarded Ad has been loaded, you will need to add `price floor` parameter to the BidMachine request. Otherwise don't pass anything, BidMachine will use the default value of **0.01$**.
`price floor` is an ad `CPM` value by adding `0.01$`. If your Mediation operates with revenue per impression you need to transform it to `CPM` by multiplying the revenue by **1000** and adding `0.01$`. `priceFloor = adRevenue * 1000 + 0.01`
```java Android (Java)
// Get revenue from mediation and convert it to CPM
mediationPrice = responseInfo.getRevenue() * 1000
// Calculate price floor
// Reponse info provides revenue per impression
double priceFloor = mediationPrice + 0.01;
// Reponse info provides CPM
// double priceFloor = responseInfo.getCPM() + 0.01;
// Make parameters object
PriceFloorParams priceFloorParams = new PriceFloorParams()
.addPriceFloor(priceFloor);
// Set object to the request
requestBuilder.setPriceFloorParams(priceFloorParams);
```
```swift iOS (Swift)
// mediationPrice default value is 0
// Calculate price floor
mediationPrice = adInfo.revenue.doubleValue * 1000
let priceFloor = mediationPrice + 0.01
// Create request configuration
let configuration = try BidMachineSdk.shared.requestConfiguration(.rewarded)
// Set price floor to the request configuration
// Name parameter is optional and can be any string
configuration.populate {
$0.appendPriceFloor(priceFloor, "Placement-\(configuration.placement.name)")
}
```
```{csharp}
// Calculate price floor
double revenue = adInfo.revenue ?? 0.0;
// Make parameters object
priceFloorParams = new PriceFloorParams();
priceFloorParams.AddPriceFloor("pdb_ironsource_rewarded", revenue*1000+0.01);
// Set object to the request
rewardedRequest = new RewardedRequest.Builder()
.SetPriceFloorParams(priceFloorParams)
.Build();
```
4. Add `mediation_mode` as `pdb` or any other value that identifies the PDB auction to request custom parameters. It will allow to split data in dashboard
```java Android (Java)
CustomParams customParams = new CustomParams()
.addParam("mediation_mode", "pdb_${PUBID}");
requestBuilder.setCustomParams(customParams);
```
```swift iOS (Swift)
configuration.populate {
$0.withCustomParameters(["mediation_mode": "pdb_is"])
}
```
```{csharp}
public CustomParams customParams;
customParams = new CustomParams();
customParams.AddParam("mediation_mode", "pdb_is");
```
5. Load BidMachine Rewarded
```java Android (Java)
rewardedAd = new RewardedAd(context)
.setListener(new BidMachineRewardedListener())
.load(requestBuilder.build());
```
```swift iOS (Swift)
BidMachineSdk.shared.rewarded(configuration) { rewarded, error in
guard let rewarded = rewarded else { return }
rewarded.loadAd()
}
```
```{csharp}
rewardedAd = new RewardedAd();
rewardedAd.SetListener(rewardedListener);
rewardedAd.Load(rewardedRequest);
```
6. Show ad.
At the impression opportunity moment, you need to check if the BidMachine ad is ready or not.
If BidMachine Interstitial wasn't loaded successfully you need to present Mediation Rewarded Ad
```java Android (Java)
if (rewardedAd != null
&& rewardedAd.canShow()
&& rewardedAd.getAuctionResult() != null
&& rewardedAd.getAuctionResult().getPrice() >= mediationPrice) {
rewardedAd.show();
} else {
mediationRewardedAd.show();
}
```
```swift iOS (Swift)
if let rewarded = rewarded, rewarded.canShow, rewarded.auctionInfo.price >= mediationPrice {
rewarded.presentAd()
} else {
mediationRewardedAd.present(from: self)
}
```
```{csharp}
if (rewardedAd.CanShow() && bidmachineRewardedPrice > MediationRewardedAd)
{
rewardedAd.Show();
}
else
{
MediationRewardedAd.show();
}
```
7. **Optional**. For the PDB auction, you might want to implement loading timeout logic. We recommend adding at least **30 seconds** loading timeout.
---
## TCF Vendor List
The [Transparency and Consent Framework](https://iabeurope.eu/transparency-consent-framework/) (TCF) is an industry standard maintained by IAB Europe and implemented by IAB Tech Lab. It provides a globally adopted, consensus‑driven set of legal, technical and operational rules — including consent strings, CMP APIs, purpose and vendor disclosures, the Global Vendor List and versioning — so publishers, CMPs and vendors can exchange interoperable consent and transparency signals, document lawful bases for processing, reduce compliance risk, and enable auditable enforcement across the ad‑tech ecosystem.
TCF "vendors" are third‑party companies (ad tech, analytics, measurement, etc.) registered in the Global Vendor List. Each vendor declares the purposes and legal bases for processing data so publishers and CMPs can present accurate choices to users. The official [Global Vendor List](https://iabeurope.eu/vendor-list-tcf/) is also maintained by IAB Europe.
Collecting user consent for all relevant vendors is important for legal compliance and auditability, ensuring each vendor only processes data for consented purposes. By enabling transparent, consent-respecting flows, publishers can access a broader set of demand partners, leading to more efficient monetization and typically higher eCPM.
CMPs (Consent Management Platforms) are tools that collect, store, and manage user consent and preferences for data processing under frameworks like the TCF. Publishers integrate CMPs to present consent choices, generate consent strings, and propagate those signals to partners so data processing and monetization remain compliant.
The list of TCF Vendors recommended by BidMachine:
```
10,Index Exchange Inc.
13,"Sovrn, Inc."
15,Adikteev
16,RTB House S.A.
23,"Nexxen Inc."
24,Epsilon
25,Yahoo EMEA Limited
28,"Triple Lift, Inc."
31,Ogury Ltd
32,Xandr
45,Equativ
50,Adform A/S
52,"Magnite, Inc. "
58,33Across
67,LifeStreet Corporation
69,OpenX
76,"PubMatic, Inc"
80,"Sharethrough, Inc"
81,"PulsePoint, Inc."
82,"Smaato, Inc."
90,Teroa S.A.
91,Criteo SA
94,Blis Global Limited
97,LiveRamp
104,"Sonobi, Inc"
108,Rich Audience Technologies SLU
109,LoopMe Limited
111,Showheroes SE
115,smartclip Europe GmbH
128,BIDSWITCH GmbH
138,ConnectAd Demand GmbH
140,Platform161 B.V.
142,Media.net Advertising FZ-LLC
143,Connatix Native Exchange Inc.
149,ADman Interactive SLU
161,"SMADEX, S.L.U."
164,Outbrain UK.
173,"Yieldmo, Inc."
192,Remerge GmbH
196,AdElement Media Solutions Pvt Ltd
210,Zemanta Inc.
231,"AcuityAds Inc."
235,Bucksense Inc
237,"VGI CTV, Inc"
238,StackAdapt Inc.
241,OneTag Limited
253,Improve Digital
254,LiquidM Technology GmbH
259,ADYOULIKE SA
262,DT Exchange (Digital Turbine (IL) Ltd.)
263,"Nativo, Inc."
276,ShowHeroes SRL
285,Freewheel (Comcast)
311,Mobfox US LLC
326,ADTIMING TECHNOLOGY PTE. LTD
333,InMobi Pte Ltd
354,Apester Ltd
358,MGID Inc.
375,RevX
380,Vidoomy Media SL
387,Triapodi Ltd. d/b/a Digital Turbine
410,Adtelligent Inc.
422,"Brand Metrics Sweden AB"
512,Verve Group Europe GmbH
527,Jampp LTD
528,Realtime Technologies GmbH
534,SmartyAds Inc.
591,"Consumable, Inc"
607,"ucfunnel Co., Ltd."
617,Onfocus (Adagio)
618,BEINTOO SPA
628,: Tappx
639,Smile Wanted Group
667,"Liftoff Monetize and Vungle Exchange"
682,Radio Net Media Limited
728,Appier PTE Ltd
733,Anzu Virtual Reality LTD
736,BidMachine Inc.
775,SelectMedia International LTD
776,Mars Media Group
779,Adtarget Teknoloji A.S.
780,Aniview LTD
803,POWERENGINE PTE.LIMITED
806,"Aarki, Inc."
807,"Moloco, Inc."
814,Eskimi
849,Epom
867,Mintegral International Limited
869,Brave People Ltd.
879,Appush Technologies
883,Online Media Solutions LTD
909,MobileFuse LLC
910,"Insticator, Inc."
957,Evolution Technologies Inc.
959,adWMG
970,Frameplay Corporation
998,Luna Media Group LLC
1022,AdView
1043,TypeA Holdings Ltd
1058,ArtChaos s.r.o.
1060,Next Millennium Media INC
1067,Arpeely Ltd.
1079,PREQUEL INTERNET TRADING LTD.
1083,Seven Technologies S.L.
1130,MobUpps International LTD
1135,Opera Software Ireland Limited
1148,ORANGE CLICK MEDIA & COMMERCE LTD
1151,Boldwin LTD
1157,Refine Direct Srl
1169,Alkimi
1176,"AlgoriX Technology Pte. Ltd.,"
1197,Axis Corp LTD
1207,Feeltapmedia Limited
1212,Ads Interactive Network Kft.
1218,AIDEM Technologies LTD
1223,Appstock LTD.
1225,Dando online LTD
1256,"Ad.com Interactive Media, Inc."
1272,BIDSCUBE SP. Z O.O
1281,Admatic GMBH
1288,TStack Inc
1292,Twist Digital LTD.
1294,Bluesea Holdings Hong Kong Limited
1298,"HONG KONG ZHIONE TECHNOLOGY CO., LIMITED"
1300,Bridgeupp LTD
1301,METAX SOFTWARE PTE.LTD.
1302,Playdigo Inc
1306,Sipo Inc
1307,EliteAppgrade
1308,SpinX Pte Ltd
1315,Krush Media LLC
1320,Xapads Media Ltd
1323,"Intent IQ LLC"
1341,Voise Tech Limited
1342,Affle Inc
1344,ProgrammaticX LTD
1352,MEDIAVERSE.AI LTD
1353,PGAM Media LLC
1356,Copper6 LTD
1357,TAURUSX INTERNATIONAL PTE. LTD.
1358,iion Digital Pty Ltd
1361,Nitrouppi LTD
1362,9 Dots Media Ltd
1366,myCast TV
1369,Mobavenue Media Pvt Ltd
1376,Carbonatix LTD
1377,"EASY TECH GROUP CO., LIMITED"
1381,Blasto sp.z.o.o.
1383,UAB Xeworks
1387,AceeX Sp.z.o.o.
1391,Bidease Inc
1404,Sahar Media FZE
1406,MARKAPP MEDIA LTD
1409,Motorik spolka z ograniczona odpowiedzialnoscia
1422,Target Better Inc
1423,Balloon Labs LLC
1425,KC Connekt Media LTD
1432,Danoler Group SP. Z O.O.
1435,ADSGO SL d/b/a ESCALAX
1437,INTEGRALSTREAM LTD
1450,Tagoras Ltd
1456,Greeter Holdings Ltd Adipolo
1457,Inteziq LTD
1461,Redmob Digital - FZCO
1466,Trendesk TV LLC dba BidFuse
1468,OnCore Digital Media
1473,Screencore Sp. z.o.o
1480,IGNITE MEDIA TECH INC
1481,Smoot technologies SL
1485,Pubx AI LTD
1486,Vlion Inc
1487,TOMATO INTERACTIVE LIMITED
1508,Persona.ly
1520,Yahoo International Limited
1535,GetmediaMX LLC
1536,HighLoadIT OU d/b/a PPC.BUZZ
1546,EYECONICSPOT LLC
1548,Azberry B.V.
1549,Unity Technologies SF
1552,Tubia FZCO
1553,Gitberry AS
1557,Bildapp LLC
1574,Madopi Media (MADOPI OÜ)
1597,SmartBid.ai LLC
```
---
## Advanced Settings(Unity)
## Global Settings
### Logs
BidMachine SDK provides logging options to help you debug and monitor the SDK's behavior.
```csharp
BidMachine.SetLoggingEnabled(true);
```
### Test Mode
BidMachine SDK can be configured to run in test mode, which is useful for testing and debugging purposes.
```csharp
BidMachine.SetTestMode(true);
```
:::warning
Test mode should be disabled in production.
:::
### Publisher Parameters
The publisher info is used to provide information about the publisher of the app.
This information is used for targeting and reporting purposes.
```csharp
BidMachine.SetPublisher(new Publisher
{
Id = "1",
Name = "Publisher Name",
Domain = "publisher.com",
Categories = new[] { "sports", "technology" }
});
```
| Parameter | Type | Description |
| :----------- | :--------- | :------------------------- |
| `Id` | `string` | Publisher ID |
| `Name` | `string` | Publisher name |
| `Domain` | `string` | Publisher domain |
| `Categories` | `string[]` | Publisher content categories |
### Targeting Parameters
The targeting info is used to provide information about the user and the app.
```csharp
var targetingParams = new TargetingParams
{
UserId = "user123",
UserGender = TargetingParams.Gender.Male,
BirthdayYear = 1990,
Keywords = new[] { "games", "sports" },
DeviceLocation = new TargetingParams.Location
{
Provider = "GPS",
Latitude = 48.8566,
Longitude = 2.3522
},
Country = "FR",
City = "Paris",
Zip = "75001",
StoreUrl = "https://play.google.com/store/apps/details?id=com.example.app",
StoreCategory = "Games",
StoreSubCategories = new[] { "Action", "Multiplayer" },
IsPaid = false,
ExternalUserIds = new[]
{
new ExternalUserId { SourceId = "ad_network_1", Value = "value_1" },
new ExternalUserId { SourceId = "ad_network_2", Value = "value_2" }
},
BlockedDomains = new HashSet { "blocked.com" },
BlockedCategories = new HashSet { "IAB25" },
BlockedApplications = new HashSet { "com.unwanted.app" }
};
BidMachine.SetTargetingParams(targetingParams);
```
`TargetingParams` can be passed in two ways:
- **Globally** — applied to all ad requests:
```csharp
BidMachine.SetTargetingParams(targetingParams);
```
- **Per ad request** — via the request builder:
```csharp
new InterstitialRequest.Builder(config)
.SetTargetingParams(targetingParams)
// ...
.Build();
```
You can combine global parameters with per-request parameters. If you set global `TargetingParams` with `UserId`, and then make a request with `TargetingParams` that has `UserGender` set, the resulting parameters will include both `UserId` and `UserGender`.
:::tip Priority of Targeting Parameters
Priority is given to the per-request parameters.
:::
## Auction Request Settings
### Price Floor Parameters
The price floor info is used to set a minimum price for the ad unit. You can pass multiple price floors for one ad request.
:::tip Price Floor Currency
The price floor is always in US dollars.
:::
If you use the method with only **price** provided, the **id** will be generated automatically using `Guid.NewGuid()`.
```csharp
var priceFloorParams = new PriceFloorParams()
.AddPriceFloor(0.01) // auto-generated id
.AddPriceFloor("custom_price_floor_id", 0.02); // explicit id
```
| Parameter | Type | Description |
| :-------- | :------- | :----------------------- |
| `id` | `string` | Unique floor identifier |
| `price` | `double` | Floor price |
To set up price floor parameters for an ad request, use `SetPriceFloorParams` on the request builder:
```csharp
new InterstitialRequest.Builder(config)
.SetPriceFloorParams(priceFloorParams)
// ...
.Build();
```
## Placement Settings
### Custom Parameters
You can pass custom parameters in the placement object to be sent to the server.
Custom parameters is a dictionary of key-value pairs that can be used for targeting or reporting purposes.
```csharp
var customParams = new CustomParams()
.AddParam("mediation_mode", "pdb_is");
```
To set up custom parameters for an ad request, use `WithCustomParams` on the placement config builder:
```csharp
var config = AdPlacementConfig.InterstitialBuilder(AdContentType.All)
.WithPlacementId("my_placement")
.WithCustomParams(customParams)
.Build();
```
## Auction Info
The auction info provides details about the ad auction,
including bid ID, creative ID, deal ID, campaign ID,
demand source, price, and custom parameters.
You can get `AuctionResult` in two ways:
- Through the request listener callback:
```csharp
public void onRequestSuccess(IAdRequest request, AuctionResult auctionResult)
{
var bidId = auctionResult.BidId;
var price = auctionResult.Price;
}
```
- Through the request object after it has been loaded:
```csharp
AuctionResult result = request.GetAuctionResultObject();
```
| Parameter | Type | Description |
| :------------- | :------------- | :----------------------------------------------------------- |
| `BidId` | `string` | Winner bid ID |
| `DemandSource` | `string` | Winner advertising source name |
| `Price` | `double` | Winner price expressed as CPM |
| `DealId` | `string` | ID of the price floor |
| `CreativeId` | `string` | Winner creative ID |
| `Cid` | `string` | Winner campaign ID or other similar grouping of brand-related ads |
| `CustomParams` | `CustomParams` | Additional parameters about the response |
| `CustomExtras` | `CustomExtras` | Winner unit extras |
---
## Banner / MREC Ads(Unity)
## Ad Request
### Placement
Create a placement configuration using `AdPlacementConfig.BannerBuilder()` with a `BannerAdSize`, optional placement id, and custom parameters.
```csharp
var config = AdPlacementConfig.BannerBuilder(BannerAdSize.Banner)
.WithPlacementId("your_placement_id") // Optional placement id
.WithCustomParams(customParams) // Optional custom parameters
.Build();
```
#### BannerAdSize
`BannerAdSize` is a required parameter for banner placement:
| Type | Size | Description |
| :----------------------------- | :------ | :---------------------------------- |
| `BannerAdSize.Banner` | 320×50 | Standard banner size |
| `BannerAdSize.Leaderboard` | 728×90 | Leaderboard banner size for tablets |
| `BannerAdSize.MediumRectangle` | 300×250 | Medium rectangle (MREC) banner |
#### Adaptive Banners
You can create adaptive banners with a custom width and maximum height:
```csharp
// Adaptive banner with width 350 and max height 100
var adaptiveSize = BannerAdSize.Adaptive(350, 100);
var config = AdPlacementConfig.BannerBuilder(adaptiveSize)
.WithPlacementId("your_placement_id")
.Build();
// Check if banner is adaptive
if (adaptiveSize.IsAdaptive)
{
// Handle responsive rendering
}
```
:::info Calculating Adaptive Height
Use `BannerAdSize.GetMaxAdaptiveHeight(width)` to get the maximum expected banner height for a given width:
```csharp
int maxHeight = BannerAdSize.GetMaxAdaptiveHeight(screenWidthDp);
var adaptiveSize = BannerAdSize.Adaptive(screenWidthDp, maxHeight);
```
:::
### Build the Request
Create a `BannerRequest.Builder` with the placement config, set optional targeting and price floor parameters, attach an `IAdAuctionRequestListener`, and call `Build()`. Building the request triggers the auction.
```csharp
var bannerRequest = (IBannerRequest)new BannerRequest.Builder(config)
.SetPriceFloorParams(priceFloorParams) // Optional price floor parameters
.SetTargetingParams(targetingParams) // Optional targeting parameters
.SetLoadingTimeOut(10000) // Optional timeout in milliseconds
.SetListener(bannerRequestListener) // Auction request listener
.Build();
```
### Auction Request Listener
Implement `IAdAuctionRequestListener` to receive auction callbacks:
```csharp
private class BannerRequestListener : IAdAuctionRequestListener
{
public void onRequestSuccess(IAdRequest request, AuctionResult auctionResult)
{
Debug.Log("BannerRequest succeeded");
}
public void onRequestFailed(IAdRequest request, BMError error)
{
Debug.Log($"BannerRequest failed: {error.Message}");
}
public void onRequestExpired(IAdRequest request)
{
Debug.Log("BannerRequest expired");
}
}
```
### Client Bidding Request
For server-to-server (S2S) integration, pass the Base64-encoded bid payload received from your server-side auction to the builder:
```csharp
var bannerRequest = (IBannerRequest)new BannerRequest.Builder(config)
.SetBidPayload(bidPayloadString)
.SetListener(bannerRequestListener)
.Build();
```
## Ad Display
### Define Ad Listener
Before loading, create a `BannerView` and set an `IAdListener` listener:
```csharp
var bannerView = new BannerView();
bannerView.SetListener(bannerListener);
bannerView.Load(bannerRequest);
```
Implement the listener to handle ad lifecycle events:
```csharp
private class BannerListener : IAdListener
{
public void onAdLoaded(IBannerView ad)
{
// Ad is loaded and ready to be displayed
}
public void onAdLoadFailed(IBannerView ad, BMError error)
{
// Ad failed to load
}
public void onAdShown(IBannerView ad)
{
// Ad has been shown
}
public void onAdShowFailed(IBannerView ad, BMError error)
{
// Ad failed to show
}
public void onAdImpression(IBannerView ad)
{
// Ad impression has been tracked
}
public void onAdExpired(IBannerView ad)
{
// Ad has expired
}
}
```
### Show the Banner
Use `onAdLoaded` to determine when the ad is ready. Before displaying, check `CanShow()`:
```csharp
if (bannerView.CanShow())
{
var size = bannerRequest.GetBannerAdSize();
bannerView.Show(
BidMachine.BannerVerticalBottom,
BidMachine.BannerHorizontalCenter,
bannerView,
size
);
}
```
#### Banner Position Constants
Use the following constants to control banner placement on screen:
| Horizontal | Vertical |
| :---------------------------------- | :-------------------------------- |
| `BidMachine.BannerHorizontalCenter` | `BidMachine.BannerVerticalCenter` |
| `BidMachine.BannerHorizontalLeft` | `BidMachine.BannerVerticalTop` |
| `BidMachine.BannerHorizontalRight` | `BidMachine.BannerVerticalBottom` |
#### Get Loaded Ad Size
Read the actual creative size in `onAdLoaded`:
```csharp
public void onAdLoaded(IBannerView ad)
{
BannerAdSize loadedSize = ad.GetAdSize();
int width = loadedSize.Width;
int height = loadedSize.Height;
}
```
### Hide the Banner
To temporarily hide the banner without destroying it:
```csharp
bannerView.Hide();
```
### Destroy the Banner
When the ad is no longer needed, clean up resources:
```csharp
bannerView.SetListener(null);
bannerView.Destroy();
bannerView = null;
bannerRequest = null;
```
:::warning
Don't destroy the `BannerRequest` if it will be used to load a `BannerView`, or if the loaded `BannerView` has not been shown yet. Premature destruction can affect display rate, fill rate, and revenue.
:::
---
## Changelog(Unity)
## Version 3.6.0 (March 13, 2026)
**Changes**:
- Updated BidMachine Android SDK to v3.6.0
- Updated BidMachine iOS SDK to v3.6.0
- Changed minimum supported Unity version to v2021.3
- Refactored Runtime and Editor scripts across all platforms
- Added `AdPlacementConfig` and `BannerAdSize` support to request builders
- Deprecated legacy banner request APIs and `IAdRequestListener`
- Removed deprecated `UserPermissions` class
- Renamed `BannerSize` members to IAB standard names; old names deprecated
- Renamed public `BidMachine` fields to PascalCase; old names deprecated
- Added `Preserve` attribute for Android callback methods
- Fixed misc typos and bugs
---
## Interstitial Ads(Unity)
## Ad Request
### Placement
Create a placement configuration using `AdPlacementConfig.InterstitialBuilder()` with an `AdContentType`, optional placement id, and custom parameters.
```csharp
var config = AdPlacementConfig.InterstitialBuilder(AdContentType.All)
.WithPlacementId("your_placement_id") // Optional placement id
.WithCustomParams(customParams) // Optional custom parameters
.Build();
```
#### AdContentType
| Type | Description |
| :--------------------- | :------------------------------------------------------------ |
| `AdContentType.All` | Flag to request both **Video** and **Static** ad content types |
| `AdContentType.Static` | Flag to request **Static** ad content type only |
| `AdContentType.Video` | Flag to request **Video** ad content type only |
### Build the Request
Create an `InterstitialRequest.Builder` with the placement config, set optional targeting and price floor parameters, attach an `IAdAuctionRequestListener`, and call `Build()`. Building the request triggers the auction.
```csharp
var interstitialRequest = new InterstitialRequest.Builder(config)
.SetPriceFloorParams(priceFloorParams) // Optional price floor parameters
.SetTargetingParams(targetingParams) // Optional targeting parameters
.SetLoadingTimeOut(10000) // Optional timeout in milliseconds
.SetListener(interstitialRequestListener) // Auction request listener
.Build();
```
### Auction Request Listener
Implement `IAdAuctionRequestListener` to receive auction callbacks:
```csharp
private class InterstitialRequestListener : IAdAuctionRequestListener
{
public void onRequestSuccess(IAdRequest request, AuctionResult auctionResult)
{
Debug.Log("InterstitialRequest succeeded");
}
public void onRequestFailed(IAdRequest request, BMError error)
{
Debug.Log($"InterstitialRequest failed: {error.Message}");
}
public void onRequestExpired(IAdRequest request)
{
Debug.Log("InterstitialRequest expired");
}
}
```
### Client Bidding Request
For server-to-server (S2S) integration, pass the Base64-encoded bid payload received from your server-side auction to the builder:
```csharp
var interstitialRequest = new InterstitialRequest.Builder(config)
.SetBidPayload(bidPayloadString)
.SetListener(interstitialRequestListener)
.Build();
```
## Ad Display
### Define Ad Listener
Before loading, create an `InterstitialAd` and set an `IInterstitialAdListener` listener:
```csharp
var interstitialAd = new InterstitialAd();
interstitialAd.SetListener(interstitialListener);
interstitialAd.Load(interstitialRequest);
```
Implement the listener to handle ad lifecycle events:
```csharp
private class InterstitialListener : IInterstitialAdListener
{
public void onAdLoaded(IInterstitialAd ad)
{
// Ad is loaded and ready to be displayed
}
public void onAdLoadFailed(IInterstitialAd ad, BMError error)
{
// Ad failed to load
}
public void onAdShown(IInterstitialAd ad)
{
// Ad has been shown
}
public void onAdShowFailed(IInterstitialAd ad, BMError error)
{
// Ad failed to show
}
public void onAdImpression(IInterstitialAd ad)
{
// Ad impression has been tracked
}
public void onAdClosed(IInterstitialAd ad, bool finished)
{
// Ad was closed
// finished indicates if the ad was completed (e.g. video played to the end)
}
public void onAdExpired(IInterstitialAd ad)
{
// Ad has expired
}
}
```
### Show the Interstitial
Use `onAdLoaded` to determine when the ad is ready. Before displaying, check `CanShow()`:
```csharp
if (interstitialAd.CanShow())
{
interstitialAd.Show();
}
```
### Destroy the Interstitial
When the ad is no longer needed, clean up resources:
```csharp
interstitialAd.SetListener(null);
interstitialAd.Destroy();
interstitialAd = null;
interstitialRequest = null;
```
:::warning
Don't destroy the `InterstitialRequest` if it will be used to load an `InterstitialAd`, or if the loaded `InterstitialAd` has not been shown yet. Premature destruction can affect display rate, fill rate, and revenue.
:::
---
## Integration(Unity)
The following page describes how to integrate the BidMachine SDK into your Unity project.
The latest BidMachine Unity Plugin version is `3.6.0`.
## Install the SDK
:::info Requirements
- **Unity**: `2021.3` or later
- **Android SDK**: `21+`
- **iOS**: `13.0+`
- **Xcode**: `15.3+`
:::
### Unity Package Manager
Add the package via the Unity Package Manager using the Git URL:
1. Open **Window → Package Manager**
2. Click the **+** button → **Add package from git URL…**
3. Enter the following URL:
```
https://github.com/bidmachine/bidmachine-unity-plugin-upm.git#v3.6.0
```
### App Tracking Transparency (iOS)
BidMachine SDK supports App Tracking Transparency (ATT) framework.
If you're unfamiliar with it, we recommend reviewing
[Apple's documentation on ATT](https://developer.apple.com/documentation/apptrackingtransparency) as part of this process.
### SKAdNetwork IDs (iOS)
The SDK supports [SKAdNetwork](https://developer.apple.com/documentation/storekit/skadnetwork/) to allow ad networks to attribute app installs even when IDFA is unavailable.
To enable this functionality, you need to add the `SKAdNetworkItems` key to your iOS project's `Info.plist` file.
1. In your exported Xcode project, select `Info.plist` in the Project navigator
2. Right-click on the `Info.plist` file → Open as → Source Code
3. Copy the SKAdNetworkItems from the [BidMachine iOS integration guide](/sdk/general/ios/overview#skadnetwork-support) and paste them into your `Info.plist` file
## Initialize the SDK
Initialize the SDK and set your **Source ID**.
:::tip
To get your `SOURCE_ID`, visit [our website](https://bidmachine.io) or contact support.
:::
```csharp
using BidMachineInc.Ads.Api;
BidMachine.Initialize("");
```
### Check Initialization Status
```csharp
bool isReady = BidMachine.IsInitialized();
```
### Set Custom Endpoint
If required, you can set a custom BidMachine endpoint before initialization:
```csharp
BidMachine.SetEndpoint("https://your-endpoint.com");
```
---
## Data Privacy(Unity)
## GDPR
Effective May 25, 2019, the European Union's General Data Protection Regulation (GDPR) has been in force.
To meet its requirements, developers can choose from these options.
### Consent Management Platform (CMP)
A Consent Management Platform (CMP) is a tool that helps developers collect, manage,
and store user consent for data processing activities.
As a publisher, you should integrate a Consent Management Platform (CMP)
that adheres to [IAB TCF v2](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/Consent%20string%20and%20vendor%20list%20formats%20v1.1%20Final.md).
Don't load any ads until the CMP has confirmed the user's consent status.
The BidMachine SDK will then consume the TCF v2 consent string supplied by your CMP.
Please note that BidMachine does not audit CMPs for full TCF compliance or adherence to applicable privacy laws.
### Manually
If you prefer not to use a CMP, you can manually collect user consent and pass it to the BidMachine SDK.
To set subject to GDPR, use the following method:
```csharp
BidMachine.SetSubjectToGDPR(true);
```
To set the GDPR consent string, use the following method.
You can pass either a valid consent string or an empty string and a boolean flag indicating
whether the user has given consent.
```csharp
BidMachine.SetConsentConfig(true, "");
```
## CCPA
Effective July 1, 2020, the California Consumer Privacy Act (CCPA) comes into force.
To pass CCPA U.S. Privacy String to BidMachine, use:
```csharp
BidMachine.SetUSPrivacyString("");
```
Also, when a compliant Consent Management Platform (CMP) is used, the SDK can automatically retrieve the CCPA U.S. Privacy String from `SharedPreferences` (Android) or `UserDefaults` (iOS).
If you would like to pass the CCPA U.S. Privacy String according to IAB standards,
please ensure your CMP stores it in `SharedPreferences` or `UserDefaults`. More information [here](https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/master/CCPA/US%20Privacy%20String.md)
and [here](https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/master/CCPA/USP%20API.md#in-app-support).
## COPPA
To help ensure compliance with COPPA, you must indicate whether a user falls within an age-restricted category.
To pass COPPA to BidMachine, use:
```csharp
BidMachine.SetCoppa(true);
```
## GPP
The Global Privacy Platform (GPP) is a unified protocol that helps advertisers, publishers,
and technology providers in digital advertising comply with evolving regulations worldwide.
By centralizing the transmission of privacy, consent, and consumer-choice signals from websites and apps to ad-tech partners,
it simplifies compliance efforts.
To pass GPP to BidMachine, there are 2 options:
### Using CMP API Specification
If you are using a Consent Management Platform (CMP) that supports the IAB's CMP API Specification,
the BidMachine SDK can automatically retrieve GPP data from `SharedPreferences` (Android) or `UserDefaults` (iOS).
### Manually
BidMachine SDK provides a method to pass GPP data directly.
This method allows you to set the GPP string and associated IDs in a straightforward manner.
```csharp
BidMachine.SetGPP("", new int[] { 2, 6 });
```
| Parameter | Type | Description |
| :---------- | :------ | :----------------------------------------------- |
| `gppString` | `string`| GPP consent string complying with the IAB standard |
| `gppIds` | `int[]` | Array of applicable GPP section IDs |
---
## Rewarded Ads(Unity)
## Ad Request
### Placement
Create a placement configuration using `AdPlacementConfig.RewardedBuilder()` with an `AdContentType`, optional placement id, and custom parameters.
```csharp
var config = AdPlacementConfig.RewardedBuilder(AdContentType.Video)
.WithPlacementId("your_placement_id") // Optional placement id
.WithCustomParams(customParams) // Optional custom parameters
.Build();
```
#### AdContentType
| Type | Description |
| :--------------------- | :------------------------------------------------------------ |
| `AdContentType.All` | Flag to request both **Video** and **Static** ad content types |
| `AdContentType.Static` | Flag to request **Static** ad content type only |
| `AdContentType.Video` | Flag to request **Video** ad content type only |
### Build the Request
Create a `RewardedRequest.Builder` with the placement config, set optional targeting and price floor parameters, attach an `IAdAuctionRequestListener`, and call `Build()`. Building the request triggers the auction.
```csharp
var rewardedRequest = new RewardedRequest.Builder(config)
.SetPriceFloorParams(priceFloorParams) // Optional price floor parameters
.SetTargetingParams(targetingParams) // Optional targeting parameters
.SetLoadingTimeOut(10000) // Optional timeout in milliseconds
.SetListener(rewardedRequestListener) // Auction request listener
.Build();
```
### Auction Request Listener
Implement `IAdAuctionRequestListener` to receive auction callbacks:
```csharp
private class RewardedRequestListener : IAdAuctionRequestListener
{
public void onRequestSuccess(IAdRequest request, AuctionResult auctionResult)
{
Debug.Log("RewardedRequest succeeded");
}
public void onRequestFailed(IAdRequest request, BMError error)
{
Debug.Log($"RewardedRequest failed: {error.Message}");
}
public void onRequestExpired(IAdRequest request)
{
Debug.Log("RewardedRequest expired");
}
}
```
### Client Bidding Request
For server-to-server (S2S) integration, pass the Base64-encoded bid payload received from your server-side auction to the builder:
```csharp
var rewardedRequest = new RewardedRequest.Builder(config)
.SetBidPayload(bidPayloadString)
.SetListener(rewardedRequestListener)
.Build();
```
## Ad Display
### Define Ad Listener
Before loading, create a `RewardedAd` and set an `IRewardedAdListener` listener:
```csharp
var rewardedAd = new RewardedAd();
rewardedAd.SetListener(rewardedListener);
rewardedAd.Load(rewardedRequest);
```
Implement the listener to handle ad lifecycle events:
```csharp
private class RewardedAdListener : IRewardedAdListener
{
public void onAdLoaded(IRewardedAd ad)
{
// Ad is loaded and ready to be displayed
}
public void onAdLoadFailed(IRewardedAd ad, BMError error)
{
// Ad failed to load
}
public void onAdShown(IRewardedAd ad)
{
// Ad has been shown
}
public void onAdShowFailed(IRewardedAd ad, BMError error)
{
// Ad failed to show
}
public void onAdImpression(IRewardedAd ad)
{
// Ad impression has been tracked
}
public void onAdRewarded(IRewardedAd ad)
{
// Rewarded ad was completed (e.g. video played to the end)
// Use this event to reward the user
}
public void onAdClosed(IRewardedAd ad, bool finished)
{
// Ad was closed
// finished indicates if the ad was completed (e.g. video played to the end)
}
public void onAdExpired(IRewardedAd ad)
{
// Ad has expired
}
}
```
### Show the Rewarded Ad
Use `onAdLoaded` to determine when the ad is ready. Before displaying, check `CanShow()`:
```csharp
if (rewardedAd.CanShow())
{
rewardedAd.Show();
}
```
### Destroy the Rewarded Ad
When the ad is no longer needed, clean up resources:
```csharp
rewardedAd.SetListener(null);
rewardedAd.Destroy();
rewardedAd = null;
rewardedRequest = null;
```
:::warning
Don't destroy the `RewardedRequest` if it will be used to load a `RewardedAd`, or if the loaded `RewardedAd` has not been shown yet. Premature destruction can affect display rate, fill rate, and revenue.
:::
---
## Integration Types
BidMachine supports various integration types to accommodate different development
environments and use cases. Below is a list of the available integration types:
## BidMachine SDK
SDK integration is the primary method for integrating BidMachine
into your mobile application if you are using custom in-house mediation solution or
if you are using a third-party mediation platform that supports BidMachine.
BidMachine SDK is presented on the following platforms:
- [Android](/sdk/general/android/overview)
- [iOS](/sdk/general/ios/overview)
- [Unity](/sdk/general/unity/overview)
## AppLovin MAX Adapter
If you are using AppLovin MAX mediation platform, you can integrate BidMachine
as an bidding adapter. Integration guides are available on [this page](/sdk/max/overview).
## Unity Level Play Adapter
If you are using Unity Level Play (IronSource) mediation platform, you can integrate BidMachine
as an bidding adapter or as custom waterfall adapter. Integration guides are available on [this page](/sdk/ironsource/overview).
## AdMob/GAM Adapter
If you are using Google Ad Manager (GAM) or AdMob mediation platform, you can integrate BidMachine
as a bidding and/or waterfall adapter. Integration guides are available on [this page](/sdk/admob/overview).
## OpenRTB Integration
For publishers using their own SSP, the preferred integration method is [OpenRTB](/sdk/ssp/overview).
---
## Adapters Compatibility
import AdapterSelect from '@site/src/components/mdx/adapter-select';
Unity Level Play Adapters for BidMachine Bidding and Waterfall are available for both Android and iOS platforms.
They are distributd as `CocoaPods Pod` for iOS and as `AAR` for Android.
- [Android GitHub repository](https://github.com/ironsource-mobile/android-adapters/tree/master/com/ironsource/adapters/bidmachineadapter)
- [iOS GitHub repository](https://github.com/ironsource-mobile/iOS-adapters/tree/master/bidmachine-adapter)
:::note
- BidMachine Bidding adapter is maintained by [Unity](https://developers.is.com/developer-docs/ios/).
- BidMachine Custom Waterfall adapter is maintained by [BidMachine](https://bidmachine.io/).
:::
Below you can find the list of supported versions for BidMachine Bidding and Waterfall adapters.
---
## Bidding Adapter
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import JavaLabel from '@site/src/components/code-labels/java'
import KotlinLabel from '@site/src/components/code-labels/kotlin'
import SwiftLabel from '@site/src/components/code-labels/swift'
import ObjCLabel from '@site/src/components/code-labels/objc'
BidMachine bidding adapter allows you to use the BidMachine ad platform
within your existing IronSource mediation.
BidMachine supports banners, MRECs, interstitials and rewarded videos.
[How to Enable BidMachine Bidding in IronSource SDK Networks Module](/sdk/ironsource/console#bidding-adapter)
:::info
Min Android SDK version - 21 (5.0 Lollipop)
:::
To integrate the BidMachine SDK with Gradle, make sure the following Maven URL exists in your `build.gradle`
```groovy title="build.gradle"
repositories {
mavenCentral()
maven {
url "https://artifactory.bidmachine.io/bidmachine"
}
}
```
In your `build.gradle` file add the following dependency which includes the BidMachine adapter for use within IronSource’s mediation platform:
```groovy title="build.gradle"
dependencies {
implementation "com.unity3d.ads-mediation:bidmachine-adapter:5.6.0"
implementation "io.bidmachine:ads:3.7.0"
}
```
## Additional Configuration
- [Advanced SDK settings](/sdk/general/android/advanced/)
- [Data Privacy settings](/sdk/general/android/privacy/)
---
## Changelog(4)
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
## Version 3.7.0.14 (May 26, 2026)
**Features**:
* Updated BidMachine version to 3.7.0
* Updated IronSource version to 9.4.2
## Version 3.6.1.13 (May 8, 2026)
**Bugfixes**
* Fixed NPE on destroy
## Waterfall Custom Adapter Version 3.6.1.12 (Aril 2, 2026)
**Features**:
* Updated BidMachine version to 3.6.1
* Updated IronSource version to 9.3.0
## Waterfall Custom Adapter Version 3.5.0.11 (November 3, 2025)
**Features**:
* Updated BidMachine version to 3.5.0
* Updated IronSource version to 9.0.0
## Waterfall Custom Adapter Version 3.4.0.10 (August 13, 2025)
**Features**:
* Updated BidMachine version to 3.4.0
* Updated IronSource version to 8.10.0
## Waterfall Custom Adapter Version 3.3.0.9 (May 28, 2025)
**Features**:
* Updated BidMachine version to 3.3.0
## Waterfall Custom Adapter Version 3.2.1.8 (May 12, 2025)
**Features**:
* Updated IronSource version to 8.8.0
## Waterfall Custom Adapter Version 3.2.1.7 (March 24, 2025)
**Features**:
* Updated BidMachine version to 3.2.1
## Waterfall Custom Adapter Version 3.2.0.6 (February 19, 2025)
**Features**:
* Updated BidMachine version to 3.2.0
* Updated IronSource version to 8.7.0
* Changed dependency from `com.ironsource.sdk:mediationsdk` to `com.unity3d.ads-mediation:mediation-sdk`
* Added `placementId` as `PriceFloorParams` id
## Waterfall Custom Adapter Version 3.1.1.5 (November 26, 2024)
**Features**:
* Updated BidMachine version to 3.1.1
* Updated IronSource version to 8.4.0
## Waterfall Custom Adapter Version 3.0.1.4 (September 18, 2024)
**Features**:
* Updated Min Android SDK version to 21 due to BidMachine update to 3.0.1.
* Updated BidMachine version to 3.0.1
* Updated IronSource version to 8.3.0
## Waterfall Custom Adapter Version 2.7.0.3 (July 3, 2024)
**Features**:
* Updated Min Android SDK version to 19 due to IronSource update to 8.1.0.
* Updated BidMachine version to 2.7.0
* Updated IronSource version to 8.1.0
---
## Waterfall Custom Adapter(Android)
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import Image from '@theme/IdealImage'
import JavaLabel from '@site/src/components/code-labels/java'
import KotlinLabel from '@site/src/components/code-labels/kotlin'
import SwiftLabel from '@site/src/components/code-labels/swift'
import ObjCLabel from '@site/src/components/code-labels/objc'
BidMachine custom adapter allows you to use the BidMachine ad platform
within your existing IronSource mediation.
BidMachine supports banners, MRECs, interstitials and rewarded videos.
## Add the BidMachine Waterfall Adapter to Your Build
:::info
Min Android SDK version - 21 (5.0 Lollipop)
:::
To integrate the BidMachine SDK with Gradle, make sure the following Maven URL exists in your `build.gradle`
```groovy title="build.gradle"
repositories {
mavenCentral()
maven {
url "https://artifactory.bidmachine.io/bidmachine"
}
}
```
In your `build.gradle` file add the following dependency which includes the BidMachine adapter for use within IronSource’s mediation platform:
```groovy title="build.gradle"
dependencies {
implementation "io.bidmachine:ads.adapters.ironsource:3.7.0.14"
implementation "io.bidmachine:ads:3.7.0"
}
```
## Additional Configuration
- [Advanced SDK settings](/sdk/general/android/advanced/)
- [Data Privacy settings](/sdk/general/android/privacy/)
---
## IronSource Bidder Specification
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjCLabel from "@site/src/components/code-labels/objc";
## Overview
BidMachine bidding supports [oRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) protocol to receive bids from supply partners and return bid responses. To integrate with BidMachine, the supply partner should integrate BidMachine SDK and the bid request should be compliant with Open RTB 2.5 Spec.
## Protocol
BidMachine service requires HTTP protocol and recommends TLS 1.2 or above.
## Request Regions
BidMachine servers are located in regions: US, EU, APAC. We highly recommend supply partners use the same region for RTB calls to avoid latency.
## Endpoint
EU region: [https://api-eu.bidmachine.io/auction/prebid/ironsource](https://api-eu.bidmachine.io/auction/prebid/ironsource)
US region: [https://api-us.bidmachine.io/auction/prebid/ironsource](https://api-us.bidmachine.io/auction/prebid/ironsource)
APAC region: [https://api-apac.bidmachine.io/auction/prebid/ironsource](https://api-apac.bidmachine.io/auction/prebid/ironsource)
## Supported Ad Formats
BidMachine only participates in mobile in-app auctions. Supported ad formats are:
- Fullscreen banner (`320x480`; `480x320`; `1024x768`; `768x1024`)
- Small banner (`320x50`; `728x90`)
- Skippable video (`320x480`; `480x320`; `1024x768`; `768x1024`)
- Rewarded video (`320x480`; `480x320`; `1024x768`; `768x1024`)
- Native Ads
## Supported Currency
USD only.
## Supported Auction Type
First-price auction Only.
## Bid Request
BidMachine server only takes one single impression in each bid request.
Key oRTB fields:
- app.bundle (required). Important note: for iOS it should be numeric and equal to application store ID
- app.storeurl (required)
- app.name (required)
- imp.instl (required)
- device.os (required)
- tmax (Required and recommended value > 1000ms)
A full BidMachine oRTB Bid Request Specification can be checked [here](/sdk/ssp/request/specification).
:::info
1. Partners should share a bid request example that they planning to use for the integration.
2. If partners have their own bid request spec and would like BidMachine to respect, please contact your BidMachine Account Manager.
:::
## Bid Response
BidMachine's bid response adheres to the **Open RTB 2.5** protocol.
### No Bid
To communicate a no-bid response, BidMachine passes an empty response with a status code 204.
### Notifications
We require `win` and `loss` notifications with the appropriate loss codes as defined in oRTB.
oRTB `NURL` and `LURL` are provided in the bid response.
If partners have any customized auction substitution macros, please notify BidMachine to support in the notification URL.
[Response](/sdk/ssp/response/examples) and [Request](/sdk/ssp/request/examples) Examples.
## Adapters
### Android
:::info
BidMachine Android SDK supported started since **v1.9.0**
:::
### Initialization
The initialization should occur once per session.
Partner initializes SDK before requesting ads.
More information [here](/sdk/general/android/overview#initialize-the-sdk).
#### Bid Token
To get a BidToken, please use one of the proposed methods:
}>
```java
// Must be run on background thread
String bidToken = BidMachine.getBidToken(context);
```
}>
```kotlin
val bidToken = BidMachine.getBidToken(context)
```
or
}>
```java
BidMachine.getBidToken(context, new BidTokenCallback() {
@Override
public void onCollected(@NonNull String bidToken) {
// The BidToken will be returned on a background thread
}
});
```
}>
```kotlin
BidMachine.getBidToken(applicationContext) { bidToken ->
// The BidToken will be returned on a background thread
}
```
#### Bid Payload
To set up bid payload for ad request use `setBidPayload` method from `AdRequest` builder according to ad type.
}>
```java
adRequestBuilder.setBidPayload(String);
```
}>
```kotlin
adRequestBuilder.setBidPayload(String)
```
[BidMachine SDK Android BidPayload Examples](https://github.com/bidmachine/BidMachine-Android-BidPayload-demo)
### iOS
:::info
BidMachine iOS SDK supported started since **v1.9.0**
:::
#### Initialization
The initialization should occur once per session.
Partner initializes SDK before requesting ads.
More information [here](/sdk/general/ios/overview#initialization)
### Bid Token
To get a BidToken, please use one of the proposed method: (api available from v1.9.0.0)
```objc
/// Generates bidder token that needs to be included in the server side bid request
@property (copy, nonatomic, readonly, nullable) NSString *biddingToken;
```
Example:
:::note
It is recommended to call the method on the background thread
:::
}>
```objc
NSString *token = BDMSdk.sharedSdk.biddingToken
```
}>
```swift
let token = BDMSdk.shared().biddingToken
```
#### Bid Payload
To set up bid payload for ad request use `setBidPayload` method from `BDMRequest`
}>
```objc
- (void)populateRequest:(BDMRequest *)request {
request.bidPayload = @"Custom payload string";
}
```
}>
```swift
func populate(_ request: BDMRequest) {
request.bidPayload = "Custom payload string"
}
```
[BidMachine SDK IOS BidPayload Examples](https://github.com/bidmachine/BidMachine-IOS-BidPayload-demo)
## Integration Testing
During the development and testing phases, BidMachine encourages you to use test mode to verify your app bidding integration.
Please use the following endpoint to test an S2S integration:
- [https://api-eu.bidmachine.io/auction/prebid/ironsource](https://api-eu.bidmachine.io/auction/prebid/ironsource)
- [https://api-us.bidmachine.io/auction/prebid/ironsource](https://api-us.bidmachine.io/auction/prebid/ironsource)
- [https://api-apac.bidmachine.io/auction/prebid/ironsource](https://api-apac.bidmachine.io/auction/prebid/ironsource)
:::warning
Bid floor: should be equal to **0.01**
Test mode should be enabled: `"test": 1`
:::
## Information Collected by SDK
| Device Data | Additional Data |
|----------------------|-----------------------|
| App bundle | SDK name |
| App version | SDK version |
| OS | impdepth |
| OS version | sessionduration |
| Device type | lastbundle |
| Connection type | lastadomain |
| Location Lat | clickrate |
| Location Lon | lastclick |
| Location Type | completionrate |
| Location Accuracy | |
| Location Lastfix | |
| Country | |
| City | |
| Zip | |
| UTC | |
| IFV (iOS Only) | |
| IFA | |
---
## Console Setup(Ironsource)
import Image from "@theme/IdealImage";
BidMachine seamlessly integrates with Unity LevelPlay (formerly IronSource) mediation as both a bidding adapter and a custom waterfall adapter, giving you the flexibility to optimize your monetization strategy. Both integration types can run simultaneously, allowing you to combine the efficiency of real-time bidding with the control of waterfall placements.
This guide covers:
- **Auto Setup**: Quick configuration using the BidMachine Helper Chrome extension
- **Manual Setup**: Step-by-step manual configuration for bidding and waterfall adapters
- **Advanced Setup**: High-value audience segmentation for increased revenue
## Auto Setup (Recommended)
The BidMachine Mediation Helper Chrome extension automates the configuration process for Unity LevelPlay.
### Installation and Setup
1. **Install the extension**
Add the [BidMachine Mediation Helper Extension](https://chromewebstore.google.com/detail/bhbbahnainkpbhpknaegjkmgffojffkb?utm_source=item-share-cb) to Chrome.
2. **Navigate to Unity LevelPlay**
Open the extension and go to the Unity LevelPlay dashboard. The extension will automatically detect your account and associated apps.
3. **Review network status**
Check the sidebar panel for any warnings about missing networks. Follow the provided instructions to add any required networks. When properly configured, you'll see confirmation messages.
### Automated Configuration
4. **Run auto setup**
Select your app and click the **Auto Setup** button. The extension will create all recommended instances (both bidding and custom waterfall) for all available ad units in the selected app.
:::note
Auto setup only creates missing instances and does not remove or modify existing configurations.
:::
### Manual Configuration (Optional)
5. **Configure custom price points**
For granular control over price points and ad units, use the manual configuration option.
6. **Create instances**
Select the ad type, configure your instance settings, and click **Create**.
7. **Verify in console**
Newly created instances will appear in the Instances section of your Unity LevelPlay console.
## Manual Setup
For advanced users who prefer manual configuration or need custom settings not available through the Chrome extension.
### Bidding Adapter
The BidMachine bidding adapter integrates BidMachine's real-time bidding capabilities into your Unity LevelPlay mediation stack. Supported ad formats include banners, MRECs, interstitials, and rewarded videos.
#### Configuration Steps
1. **Navigate to SDK Networks**
Log in to your Unity LevelPlay account and go to **Monetize** → **Setup** → **SDK Networks**.
2. **Activate BidMachine**
- Locate BidMachine in the Available Networks table
- Click the **Activate** button
- Enter your BidMachine credentials
- Click **Save**
3. **Configure the network**
Select BidMachine from your list of ad networks and click **Setup**.
4. **Enable ad units**
Activate the ad units you want to use with BidMachine bidding.
### Waterfall Adapter
The BidMachine waterfall adapter allows you to integrate BidMachine into your mediation waterfall with manual price control. Supported ad formats include banners, MRECs, interstitials, and rewarded videos.
#### Network Setup
1. **Navigate to SDK Networks**
Log in to your Unity LevelPlay account and go to **LevelPlay** → **Setup** → **SDK Networks**.
2. **Add custom network**
- Click **Setup Custom Network**
- Enter Network Key: `15bfce4b5`
- Click **Enter key** and then **Save**
3. **Configure revenue settings**
- Enter the **Source ID** provided by BidMachine
- Select **Rate based revenue** as the revenue model
- Click **Save**
Your BidMachine waterfall network is now configured and ready for instance creation.
#### Instance Setup
After configuring the BidMachine waterfall network, create instances for your ad units.
1. **Access instances**
Navigate to **SDK Networks** in your Unity LevelPlay account.
2. **Select BidMachine Waterfall**
- Go to the Custom section
- Select **BidMachine Waterfall**
- Click **Setup**
3. **Configure instance settings**
- **Placement ID**: Enter the Placement ID from your [BidMachine Dashboard](/dashboard/placement) (optional, see Advanced Setup below for use cases)
- **Price**: Set the CPM price for this instance
- **Mediation Group**: Select your target mediation group
- **Rate**: Enter the rate for waterfall sorting (important for correct prioritization)
- Click **Save**
:::tip Multiple Placements
BidMachine supports multiple placements in the waterfall. Always enter the **Rate** value to ensure correct waterfall ordering and optimal performance.
:::
## Advanced Setup: High-Value Audience Segmentation
### Overview
Maximize revenue by leveraging Placement IDs to differentiate and optimize for your most valuable users. By assigning **Placement IDs** to specific user segments in your Unity LevelPlay setup, you enable BidMachine to recognize ad requests from your **high-value audience (HVA)** and apply custom optimization strategies.
#### Benefits
Placement IDs unlock advanced optimization capabilities:
- **Differentiated HVA traffic** – BidMachine's ad server identifies high-value users and applies tailored strategies including optimized price floors and bidding aggressiveness
- **Revenue uplift** – Publishers typically see **5-15% performance improvement** on HVA segments
- **Transparent reporting** – Separate metrics for each placement provide clear visibility into segment performance
#### User Segmentation Strategies
If you're not currently segmenting users, you can start by using your first-party data. Common segmentation approaches include:
| Segment Type | Definition | Expected Uplift |
|--------------|------------|-----------------|
| **Revenue-based** | Top 20% of users by historical IAA revenue (last 7-30 days) | 5-10% |
| **CPM-based** | Top 20% of users by average CPM across all ad networks | 5-10% |
| **IAP users** | Users who have made at least one in-app purchase | 10-15% |
| **Engagement-based** | Users with high session length or time spent in app | Varies |
Once you've defined your segments, create dedicated Placement IDs for each HVA segment and share them with your BidMachine account manager.
#### Implementation Steps
Follow these steps to implement HVA segmentation with Placement IDs:
1. **Define your segments**
Identify your high-value user segments using the strategies outlined above.
2. **Create Placement IDs**
Generate Placement IDs in your [BidMachine Dashboard](/dashboard/placement) for each HVA segment.
3. **Configure Unity LevelPlay instances**
**a. Navigate to instances**
Go to **Setup** → **Instances** in your Unity LevelPlay dashboard and select BidMachine.
**b. Create dual instances**
For each ad unit, create two separate instances:
- **Standard instance**: For regular users (your existing configuration)
- **HVA instance**: For high-value users, with the BidMachine Placement ID specified
**c. Implement dynamic instance selection**
In your app code, dynamically select the appropriate instance when generating ad requests based on the user's segment classification.
4. **Automatic optimization**
BidMachine's SDK and ad server will automatically apply optimized strategies for your HVA traffic.
5. **Optional: Validation**
Verify your implementation with the BidMachine team:
- Include the test IDFA provided by BidMachine in your HVA segment
- Share a debug build of your application
- BidMachine will validate the integration and confirm proper segmentation
:::success
By implementing Placement IDs, you enable BidMachine to fully leverage your user segmentation, delivering optimized targeting, increased demand competition, and higher eCPMs for your most valuable users.
:::
---
## Bidding Adapter(Ios)
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import JavaLabel from '@site/src/components/code-labels/java'
import KotlinLabel from '@site/src/components/code-labels/kotlin'
import SwiftLabel from '@site/src/components/code-labels/swift'
import ObjCLabel from '@site/src/components/code-labels/objc'
BidMachine bidding adapter allows you to use the BidMachine ad platform
within your existing IronSource mediation.
BidMachine supports banners, MRECs, interstitials and rewarded videos.
[How to Enable BidMachine Bidding in IronSource SDK Networks Module](/sdk/ironsource/console#bidding-adapter)
:::info
IOS deployment target 13.0 or above, XCode 14.3.1 or above.
:::
You can download the SDK through CocoaPods as a dependency.
In your **Podfile** file add the following dependency which includes the BidMachine adapter for use within IronSource's mediation platform:
```ruby title="Podfile"
pod 'IronSourceBidMachineAdapter','5.4.0.0'
```
## Additional Configuration
- [Advanced SDK settings](/sdk/general/ios/advanced/)
- [Data Privacy settings](/sdk/general/ios/privacy/)
---
## Changelog(5)
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
## Waterfall Custom Adapter Version 3.7.0.0 (May 27th, 2026)
- Certified with BidMachine 3.7.0
- Certified with IronSource 9.4.0
## Waterfall Custom Adapter Version 3.6.0.0 (Apr 2nd, 2025)
- Certified with BidMachine 3.6.0
- Certified with IronSource 9.3.0
## Waterfall Custom Adapter Version 3.5.0.4 (Dec 2nd, 2025)
- Certified with IronSource 9.2.0
## Waterfall Custom Adapter Version 3.5.0.1 (Nov 12th, 2025)
- Certified with IronSource 9.1.0
- Certified with BidMachine 3.5.0
## Waterfall Custom Adapter Version 3.5.0.0 (Nov 7th, 2025)
- Certified with IronSource 9.0.0
- Certified with BidMachine 3.5.0
## Waterfall Custom Adapter Version 3.4.0.1 (Aug 25th, 2025)
- Certified with IronSource 8.11.0
## Waterfall Custom Adapter Version 3.4.0.0 (Aug 13th, 2025)
- Certified with BidMachine 3.4.0
## Waterfall Custom Adapter Version 3.3.0.4 (July 21th, 2025)
- Certified with IronSource 8.10.0
- Rewarded and interstitial adDidShowSucceed callback fix
## Waterfall Custom Adapter Version 3.3.0.3 (July 21th, 2025)
- Certified with IronSource 8.9.1
- Rewarded and interstitial adDidShowSucceed callback fix
## Waterfall Custom Adapter Version 3.3.0.2 (July 17th, 2025)
- Certified with IronSource 8.10.0
## Waterfall Custom Adapter Version 3.3.0.1 (June 18th, 2025)
- Certified with IronSource 8.9.1
- Set minimum deployment target to iOS 12.0
## Waterfall Custom Adapter Version 3.3.0.0 (May 29th, 2025)
- Certified with BidMachine 3.3.0
## Waterfall Custom Adapter Version 3.2.1.1 (May 16th, 2025)
- Certified with IronSource 8.8.0
## Waterfall Custom Adapter Version 3.2.1.0 (Mar 24th, 2025)
- Certified with BidMachine 3.2.1
- Certified with IronSource 8.7.0
## Waterfall Custom Adapter Version 3.2.0.1 (Feb 19th, 2025)
- Certified with BidMachine 3.2.0
- Certified with IronSource 8.7.0
## Waterfall Custom Adapter Version 3.2.0.0 (Feb 14th, 2025)
- Certified with BidMachine 3.2.0
- Certified with IronSource 8.6.0
## Waterfall Custom Adapter Version 3.1.1.0 (Jan 22th, 2025)
- Certified with BidMachine 3.1.1
- Certified with IronSource 8.6.0
## Waterfall Custom Adapter Version 3.0.1.1 (Dec 11th, 2024)
- Certified with BidMachine 3.0.1
- Certified with IronSource 8.1.0
## Waterfall Custom Adapter Version 3.1.1 (Dec 4th, 2024)
- Update BM 3.1.1
- Update IS 8.4.0
## Waterfall Custom Adapter Version 3.1.0 (Nov 5th, 2024)
- Update BM 3.1.0
## Waterfall Custom Adapter Version 3.0.1 (Sep 16th, 2024)
- Update IS 8.3.0
- Update BM 3.0.1
## Waterfall Custom Adapter Version 2.7.0 (May 14th, 2024)
- Update IS 8.0.0
- Update BM 2.7.0
## Waterfall Custom Adapter Version 2.5.2 (Mar 28th, 2024)
- Update IS 7.9.1
## Waterfall Custom Adapter Version 2.5.1 (Mar 8th, 2024)
- Add mediation_mode field
## Waterfall Custom Adapter Version 2.5.0 (Mar 6th, 2024)
- Initial adapter
---
## Waterfall Custom Adapter(3)
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import Image from '@theme/IdealImage'
import JavaLabel from '@site/src/components/code-labels/java'
import KotlinLabel from '@site/src/components/code-labels/kotlin'
import SwiftLabel from '@site/src/components/code-labels/swift'
import ObjCLabel from '@site/src/components/code-labels/objc'
BidMachine custom adapter allows you to use the BidMachine ad platform
within your existing IronSource mediation.
BidMachine supports banners, MRECs, interstitials and rewarded videos.
## Add the BidMachine Bidding Adapter to Your Build
:::info
IOS deployment target 13.0 or above, XCode 14.3.1 or above.
:::
You can download the SDK through CocoaPods as a dependency.
In your **Podfile** file add the following dependency which includes the BidMachine adapter for use within IronSource's mediation platform:
```ruby title="Podfile"
source 'https://github.com/cocoapods/specs'
pod 'BidMachineIronSourceCustomAdapter', '3.7.0.0'
```
## Additional Configuration
- [Advanced SDK settings](/sdk/general/ios/advanced/)
- [Data Privacy settings](/sdk/general/ios/privacy/)
---
## Overview(Ironsource)
This page gives you step-by-step instructions for how you set BidMachine live as an ad network on the Unity Level Play (IronSource) Mediation platform.
## How to Create a BidMachine Account?
Create a BidMachine Account at [bidmachine.io](https://bidmachine.io/#sign-up).
## Activate Account
Upon registration, an activation email containing instructions will be sent
to the email address you've provided. Please use the provided instructions
to activate your account.
## Retrieve and Configure the Source ID
To enable BidMachine Ad Inventory through the IronSource Mediation platform, you must have an approved monetization account with BidMachine.
Your account manager should provide you with the **Source ID**, or you may follow the documentation guide.
If you already have a BidMachine Account, refer to the next page: [How to get Source ID under BidMachine Dashboard](/dashboard/source)
## Testing instructions
Before deploying the BidMachine SDK and adapter to your live application, you can perform testing with the test mode.
This will guarantee a high fill rate (99.99%) during the integration testing process,
ensuring that the implementation is functioning correctly. It is crucial to disable the test mode before going live, as failing to do so will result in financial loss.
## Revenue Reports
You will be provided with a dashboard, please contact your account manager who will share the credentials with you.
## Mediation Types
BidMachine supports the following mediation types:
- [**Bidding Adapter**](/sdk/ironsource/console#bidding-adapter) - BidMachine bidding adapter allows you to use the BidMachine ad platform within your existing IronSource mediation.
- [**Waterfall Custom Adapter**](/sdk/ironsource/console#waterfall-adapter) - BidMachine custom adapter allows you to use the BidMachine ad platform within your existing IronSource mediation.
:::success
We recommend using the hybrid mediation type (both bidding and waterfall) to maximize your fill rate.
:::
---
## IronSource Publisher Direct Bidding (PDB)
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
## How to add BidMachine to Publisher Direct Bidding (PDB) auction within IronSource mediation
BidMachine could be easily integrated into the PDB auction.
Documentation on how to integrate BidMachine SDK can be found [here](/sdk/overview)
Step-by-step integration is the following:
- At the start of the application, BidMachine should be initialized according to the doc (section: Initialisation)
- The publisher requests an ad from IronSource and fetches the price of it according to the [following documentation](https://developers.is.com/ironsource-mobile/android/levelplay-listener-adinfo-integration/#step-3)
- The publisher requests an ad from BidMachine with the price that was returned by mediation plus 0.01$, other PDB partners should be requested with the same price
- If BidMachine wins the PDB auction - the publisher loads it's creative and uses it for impressions later
If there are multiple demand sources in the PDB auction, the publisher should notify BidMachine with win and loss notification. Publisher shall populate the auction winning price via a loss notice URL according to this documentation: [iOS](https://docs.bidmachine.io/docs/in-house-mediation-1#mediation), [Android](https://docs.bidmachine.io/docs/in-house-mediation#winloss-notifications).
The publisher should set up an interval for the BidMachine request in PDB not less than:
- **10 seconds** for Banner/MREC
- **15 seconds** for Interstitial
- **30 seconds** for Rewarded Video
### Integration
You need to add both IronSource and BidMachine SDK into your project:
```groovy title="build.gradle"
repositories {
maven {
url "https://android-sdk.is.com/"
}
maven {
url "https://artifactory.bidmachine.io/bidmachine"
}
}
dependencies {
implementation "com.ironsource.sdk:mediationsdk:8.2.1"
implementation "io.bidmachine:ads:3.0.0"
}
```
```ruby title="Podfile"
pod 'IronSourceSDK', '~> 8.2.0'
pod 'IronSourceAdQualitySDK', '~> 7.20'
pod 'BidMachine', '~> 3.0.0'
```
### Initialization
Change your IronSource SDK initialization logic. BidMachine SDK should be properly configured and initialized before IronSource SDK will be initialized.
:::warning
If you want to use BidMachine in a PDB auction for rewarded ads,
you need to set `LevelPlayRewardedVideoManualListener` before initialization
and load ads manually, just like interstitials.
:::
```java title="MainActivity.java"
// 1. Prepare BidMachine environment - GDPR, CCPA, GPP, Coppa, test mode, etc...
// 2. Initializing BidMachine
BidMachine.initialize(context, "");
// 3. Prepare IronSource environment - GDPR, CCPA, Coppa, etc...
// 4. Set listeners
IronSource.setLevelPlayInterstitialListener(new IronSourceInterstitialListener());
IronSource.setLevelPlayRewardedVideoManualListener(new IronSourceRewardedManualListener());
// 5. Initializing IronSource
IronSource.init(context, "");
```
```swift title="AppDelegate.swift"
// 1. Prepare BidMachine environment - GDPR, CCPA, GPP, Coppa, test mode, etc...
/**
BidMachineSdk.shared.populate {
$0.withLoggingMode(true)
}
*/
// 2. Initializing BidMachine
BidMachineSdk.shared.initializeSdk("")
// 3. Prepare IronSource environment - GDPR, CCPA, Coppa, etc...
/**
IronSource.setConsent(true)
*/
// 4. Set delegates
IronSource.setLevelPlayInterstitialDelegate(<#T##delegate: (any LevelPlayInterstitialDelegate)?##(any LevelPlayInterstitialDelegate)?#>)
IronSource.setLevelPlayRewardedVideoManualDelegate(<#T##delegate: (any LevelPlayRewardedVideoManualDelegate)?##(any LevelPlayRewardedVideoManualDelegate)?#>)
// 5. Initialize IronSource
IronSource.initWithAppKey("")
```
```csharp title="MainActivity.cs"
// 1. Prepare BidMachine environment - GDPR, CCPA, GPP, Coppa, test mode, etc...
// 2. Initializing BidMachine
BidMachine.Initialize("");
// 3. Prepare IronSource environment - GDPR, CCPA, Coppa, etc...
// 4. Set listeners
// 5. Set IronSource rewarded loading to manual
IronSource.Agent.setManualLoadRewardedVideo(true);
// 5. Initializing IronSource
IronSource.Agent.init("appKey");
```
:::warning
The placement capping feature is not available for the PDB auction
:::
### Interstitial
To implement PDB auction over Interstitial Ad you need to follow the next steps:
1. **Load IronSource Interstitial**
```java Android title="MyClass.java"
IronSource.loadInterstitial();
```
```swift title="MyClass.swift"
IronSource.loadInterstitial()
```
```csharp title="MyClass.cs"
IronSource.Agent.loadInterstitial();
```
2. **Handle loading callback methods from `LevelPlayInterstitialDelegate`**
```java title="MyClass.java"
@Override
public void onAdReady(AdInfo adInfo) {
loadBidMachineInterstitial(adInfo);
}
@Override
public void onAdLoadFailed(IronSourceError ironSourceError) {
loadBidMachineInterstitial(null);
}
```
```swift title="MyClass.swift"
func didLoad(with adInfo: ISAdInfo!) {
loadBidMachineInterstitial(adInfo)
}
func didFailToLoadWithError(_ error: (any Error)!) {
loadBidMachineInterstitial(nil)
}
```
```csharp title="MyClass.cs"
public void InterstitialOnAdReadyEvent(IronSourceAdInfo adInfo)
{
LoadBidMachineInterstitialPDB(adInfo);
}
public void InterstitialOnAdLoadFailed(IronSourceError ironSourceError)
{
LoadBidMachineInterstitialAd();
}
```
3. **Load BidMachine Interstitial**. If IronSource Interstitial has been loaded,
you will need to add `price floor` to the BidMachine request.
Otherwise don't pass anything, BidMachine will use the default value of **0.01$**.
`price floor` is a `revenue` value from `AdInfo` object
transformed to `CPM` (multiplied by **1000**) by adding `0.01$`.
`priceFloor = adInfo.revenue * 1000 + 0.01`
```java title="MyClass.java"
// Get revenue from IronSource and convert it to CPM
ironSourcePrice = adInfo.getRevenue() * 1000
// Calculate price floor
double priceFloor = ironSourcePrice + 0.01;
// Make parameters object
PriceFloorParams priceFloorParams = new PriceFloorParams()
.addPriceFloor(priceFloor);
// Set object to the request
requestBuilder.setPriceFloorParams(priceFloorParams);
```
```swift title="MyClass.swift"
// Calculate price floor
let priceFloor = adInfo.revenue.doubleValue * 1000 + 0.01
// Create request configuration
let configuration = try BidMachineSdk.shared.requestConfiguration(.interstitial)
// Set price floor to the request configuration
// Name parameter is optional and can be any string
configuration.populate {
$0.appendPriceFloor(priceFloor, "Placement-\(configuration.placement.name)")
}
```
```csharp title="MyClass.cs"
// Calculate price floor
double revenue = adInfo.revenue ?? 0.0;
// Make parameters object
priceFloorParams = new PriceFloorParams();
priceFloorParams.AddPriceFloor("pdb_ironsource_inter", revenue*1000+0.01);
// Set object to the request
interstitialRequest = new InterstitialRequest.Builder()
.SetPriceFloorParams(priceFloorParams)
.Build();
```
4. **Add `mediation_mode` as `pdb_is` to request custom parameters**.
It will allow the split data in the dashboard
```java title="MyClass.java"
CustomParams customParams = new CustomParams()
.addParam("mediation_mode", "pdb_is");
requestBuilder.setCustomParams(customParams);
```
```swift title="MyClass.swift"
configuration.populate {
$0.withCustomParameters(["mediation_mode": "pdb_is"])
}
```
```csharp title="MyClass.cs"
public CustomParams customParams;
customParams = new CustomParams();
customParams.AddParam("mediation_mode", "pdb_is");
```
5. **Load BidMachine Interstitial**
```java title="MyClass.java"
interstitialAd = new InterstitialAd(context)
.setListener(new BidMachineInterstitialListener())
.load(requestBuilder.build());
```
```swift title="MyClass.swift"
BidMachineSdk.shared.interstitial(configuration) { interstitial, error in
guard let interstitial = interstitial else { return }
interstitial.loadAd()
}
```
```csharp title="MyClass.cs"
interstitialAd = new InterstitialAd();
interstitialAd.SetListener(interstitialListener);
interstitialAd.Load(interstitialRequest);
```
6. **Show ad**. At the impression opportunity moment, you need to check if the BidMachine ad is ready or not.
If BidMachine Interstitial wasn't loaded successfully you need to call IronSource interstitial show method.
```java title="MyClass.java"
if (interstitialAd != null
&& interstitialAd.canShow()
&& interstitialAd.getAuctionResult() != null
&& interstitialAd.getAuctionResult().getPrice() >= ironSourcePrice) {
interstitialAd.show();
} else {
IronSource.showInterstitial();
}
```
```swift title="MyClass.swift"
if let interstitial = interstitial, interstitial.canShow, interstitial.auctionInfo.price >= ironSourcePrice {
interstitial.presentAd()
} else {
IronSource.showInterstitial(with: self)
}
```
```csharp title="MyClass.cs"
if (interstitialAd.CanShow()&& bidmachineInterPrice > ironSourceInter)
{
interstitialAd.Show();
}
else
{
IronSource.Agent.showInterstitial();
}
```
7. _Optional_. For the PDB auction, you might want to implement loading timeout logic.
We recommend adding at least **15 seconds** loading timeout.
Full Interstitial PDB auction integration sample:
```java title="MyClass.java"
private void loadInterstitial() {
IronSource.loadInterstitial();
}
private void loadBidMachineInterstitial(@Nullable AdInfo adInfo) {
if (interstitialAd != null) {
interstitialAd.destroy();
}
InterstitialRequest.Builder requestBuilder = new InterstitialRequest.Builder();
if (adInfo != null) {
// Get revenue from IronSource and convert it to CPM
ironSourcePrice = adInfo.getRevenue() * 1000
// Calculate price floor
double price = ironSourcePrice + 0.01;
PriceFloorParams priceFloorParams = new PriceFloorParams()
.addPriceFloor(price);
requestBuilder.setPriceFloorParams(priceFloorParams);
}
CustomParams customParams = new CustomParams()
.addParam("mediation_mode", "pdb_is");
requestBuilder.setCustomParams(customParams);
interstitialAd = new InterstitialAd(context)
.setListener(new BidMachineInterstitialListener())
.load(requestBuilder.build());
}
private void onLoadInterstitialCompleted() {
// Handling the end of loading
}
private void showInterstitial() {
if (interstitialAd != null
&& interstitialAd.canShow()
&& interstitialAd.getAuctionResult() != null
&& interstitialAd.getAuctionResult().getPrice() >= ironSourcePrice) {
interstitialAd.show();
} else {
IronSource.showInterstitial();
}
}
private class IronSourceInterstitialListener implements LevelPlayInterstitialListener {
@Override
public void onAdReady(AdInfo adInfo) {
loadBidMachineInterstitial(adInfo);
}
@Override
public void onAdLoadFailed(IronSourceError ironSourceError) {
loadBidMachineInterstitial(null);
}
// Other callbacks
}
private class BidMachineInterstitialListener implements InterstitialListener {
@Override
public void onAdLoaded(@NonNull InterstitialAd interstitialAd) {
onLoadInterstitialCompleted();
}
@Override
public void onAdLoadFailed(@NonNull InterstitialAd interstitialAd, @NonNull BMError bmError) {
onLoadInterstitialCompleted();
}
// Other callbacks
}
```
```swift title="MyClass.swift"
final class ViewController: UIViewController {
private var interstitial: BidMachineInterstitial?
private var ironSourcePrice: Double = 0
override func viewDidLoad() {
super.viewDidLoad()
// Set delegate if needed
// IronSource.setLevelPlayInterstitialDelegate(self)
loadIronSourceInterstitial()
}
private func loadIronSourceInterstitial() {
IronSource.loadInterstitial()
}
private func loadBidMachineInterstitial(_ adInfo: ISAdInfo?) throws {
let configuration = try BidMachineSdk.shared.requestConfiguration(.interstitial)
if let adInfo = adInfo {
ironSourcePrice = adInfo.revenue.doubleValue * 1000
let priceFloor = ironSourcePrice + 0.01
configuration.populate {
$0.appendPriceFloor(priceFloor, "Placement-\(configuration.placement.name)")
}
}
configuration.populate {
$0.withCustomParameters(["mediation_mode": "pdb_is"])
}
BidMachineSdk.shared.interstitial(configuration) { [weak self] interstitial, error in
guard
let self = self,
let interstitial = interstitial
else { return }
interstitial.controller = self
interstitial.delegate = self
self.interstitial = interstitial
interstitial.loadAd()
}
}
private func showInterstitial() {
if let interstitial = interstitial, interstitial.canShow, interstitial.auctionInfo.price >= ironSourcePrice {
interstitial.presentAd()
} else {
IronSource.showInterstitial(with: self)
}
}
}
extension ViewController: LevelPlayInterstitialDelegate {
func didLoad(with adInfo: ISAdInfo!) {
try? loadBidMachineInterstitial(adInfo)
}
func didFailToLoadWithError(_ error: (any Error)!) {
try? loadBidMachineInterstitial(nil)
}
func didOpen(with adInfo: ISAdInfo!) {}
func didShow(with adInfo: ISAdInfo!) {}
func didFailToShowWithError(_ error: (any Error)!, andAdInfo adInfo: ISAdInfo!) {}
func didClick(with adInfo: ISAdInfo!) {}
func didClose(with adInfo: ISAdInfo!) {}
}
extension ViewController: BidMachineAdDelegate {
func didLoadAd(_ ad: any BidMachine.BidMachineAdProtocol) {}
func didFailLoadAd(_ ad: any BidMachine.BidMachineAdProtocol, _ error: any Error) {}
}
```
```csharp title="MyClass.cs"
public static double bidmachineInterPrice;
public double ironSourceInter;
public CustomParams customParams;
public void LoadInterstitial()
{
IronSource.Agent.loadInterstitial();
}
public void LoadBidMachineInterstitialPDB(IronSourceAdInfo adInfo)
{
if (interstitialRequest != null)
{
interstitialAd.SetListener(null);
interstitialAd.Destroy();
interstitialAd = null;
interstitialRequest = null;
}
customParams = new CustomParams();
customParams.AddParam("mediation_mode", "pdb_is");
double revenue = adInfo.revenue ?? 0.0;
priceFloorParams = new PriceFloorParams();
priceFloorParams.AddPriceFloor("pdb_is_inter", revenue*1000+0.1);
interstitialRequest = new InterstitialRequest.Builder()
.SetAdContentType(AdContentType.All)
.SetPriceFloorParams(priceFloorParams)
// .SetTargetingParams(targetingParams)
// .SetPlacementId("placement_interstitialRequest")
// .SetLoadingTimeOut(10 * 1000)
// .SetBidPayload("123")
// .SetNetworks("admob")
.SetCustomParams(customParams)
.SetListener(interstitialRequestListener)
.Build();
if (interstitialAd != null)
{
interstitialAd.SetListener(null);
interstitialAd.Destroy();
interstitialAd = null;
}
interstitialAd = new InterstitialAd();
interstitialAd.SetListener(interstitialListener);
interstitialAd.Load(interstitialRequest);
}
public void ShowInterstitial()
{
if (interstitialAd.CanShow() && bidmachineInterPrice > ironSourceInter)
{
interstitialAd.Show();
}
else
{
IronSource.Agent.showInterstitial();
}
}
// ironSource interstitial callbacks
public void InterstitialOnAdReadyEvent(IronSourceAdInfo adInfo)
{
LoadBidMachineInterstitialPDB(adInfo);
ironSourceInter = adInfo.revenue ?? 0.0;
}
public void InterstitialOnAdLoadFailed(IronSourceError ironSourceError)
{
// Load BidMachine ad without postbid
LoadBidMachineInterstitialAd();
}
public void InterstitialOnAdClosedEvent(IronSourceAdInfo adInfo)
{
IronSource.Agent.loadInterstitial();
}
// Other callback
//BidMachine interstitial callbacks
private class InterstitialListener : IInterstitialAdListener
{
public void onAdClosed(IInterstitialAd ad, bool finished)
{
IronSource.Agent.loadInterstitial();
}
// Other callbacks
}
//BidMachine interstitial request callbacks
private class InterstitialRequestListener : IAdRequestListener
{
public void onRequestExpired(IAdRequest request)
{
Debug.Log("BidMachine: InterstitialRequest: OnAdRequestExpired");
}
public void onRequestFailed(IAdRequest request, BMError error)
{
Debug.Log($"BidMachine: InterstitialRequest: OnAdRequestFailed");
}
public void onRequestSuccess(IAdRequest request, string auctionResult)
{
Debug.Log($"BidMachine: InterstitialRequest: OnAdRequestSuccess");
BidMachineAdInfo bidMachineAdInfoinfo = JsonUtility.FromJson(auctionResult);
Debug.Log($"/* INTERSTITIAL PRICE */" + bidMachineAdInfoinfo.price);
bidmachineInterPrice = bidMachineAdInfoinfo.price;
}
}
public class BidMachineAdInfo
{
public string demandSource;
public string creativeID;
public string bidID;
public string cID;
public double price;
public string dealID;
}
```
### Rewarded Ad
To implement PDB auction over Rewarded Ad you need to follow the next steps:
1. **Load IronSource Rewarded**
```java title="MyClass.java"
IronSource.loadRewardedVideo();
```
```swift title="MyClass.swift"
IronSource.loadRewardedVideo()
```
```csharp title="MyClass.cs"
IronSource.Agent.loadRewardedVideo();
```
2. **Handle loading callback methods from `LevelPlayRewardedVideoManualDelegate`**
```java title="MyClass.java"
@Override
public void onAdReady(AdInfo adInfo) {
loadBidMachineRewarded(adInfo);
}
@Override
public void onAdLoadFailed(IronSourceError ironSourceError) {
loadBidMachineRewarded(null);
}
```
```swift title="MyClass.swift"
func didLoad(with adInfo: ISAdInfo!) {
loadBidMachineRewarded(adInfo)
}
func didFailToLoadWithError(_ error: (any Error)!) {
loadBidMachineRewarded(nil)
}
```
```csharp title="MyClass.cs"
public void RewardedOnAdReadyEvent(IronSourceAdInfo adInfo)
{
LoadBidMachineRewardedPDB(adInfo);
}
public void RewardedOnAdLoadFailed(IronSourceError ironSourceError)
{
LoadBidMachinerewardedAd();
}
```
3. **Load BidMachine Rewarded**. If IronSource Interstitial has been loaded,
you will need to add `price floor` to the BidMachine request. Otherwise don't pass anything,
BidMachine will use the default value of **0.01$**.
`price floor` is a `revenue` value from `AdInfo` object transformed to `CPM` (multiplied by **1000**) by adding `0.01$`. `priceFloor = adInfo.revenue * 1000 + 0.01`
```java title="MyClass.java"
// Get revenue from IronSource and convert it to CPM
ironSourcePrice = adInfo.getRevenue() * 1000
// Calculate price floor
double priceFloor = ironSourcePrice + 0.01;
// Make parameters object
PriceFloorParams priceFloorParams = new PriceFloorParams()
.addPriceFloor(priceFloor);
// Set object to the request
requestBuilder.setPriceFloorParams(priceFloorParams);
```
```swift title="MyClass.swift"
// Calculate price floor
let priceFloor = adInfo.revenue.doubleValue * 1000 + 0.01
// Create request configuration
let configuration = try BidMachineSdk.shared.requestConfiguration(.rewarded)
// Set price floor to the request configuration
// Name parameter is optional and can be any string
configuration.populate {
$0.appendPriceFloor(priceFloor, "Placement-\(configuration.placement.name)")
}
```
```csharp title="MyClass.cs"
// Calculate price floor
double revenue = adInfo.revenue ?? 0.0;
// Make parameters object
priceFloorParams = new PriceFloorParams();
priceFloorParams.AddPriceFloor("pdb_ironsource_rewarded", revenue*1000+0.01);
// Set object to the request
rewardedRequest = new RewardedRequest.Builder()
.SetPriceFloorParams(priceFloorParams)
.Build();
```
4. **Add `mediation_mode` as `pdb_is` to request custom parameters**. It will allow to split data in dashboard
```java title="MyClass.java"
CustomParams customParams = new CustomParams()
.addParam("mediation_mode", "pdb_is");
requestBuilder.setCustomParams(customParams);
```
```swift title="MyClass.swift"
configuration.populate {
$0.withCustomParameters(["mediation_mode": "pdb_is"])
}
```
```csharp title="MyClass.cs"
public CustomParams customParams;
customParams = new CustomParams();
customParams.AddParam("mediation_mode", "pdb_is");
```
5. **Load BidMachine Rewarded**.
```java title="MyClass.java"
rewardedAd = new RewardedAd(context)
.setListener(new BidMachineRewardedListener())
.load(requestBuilder.build());
```
```swift title="MyClass.swift"
BidMachineSdk.shared.rewarded(configuration) { rewarded, error in
guard let rewarded = rewarded else { return }
rewarded.loadAd()
}
```
```csharp title="MyClass.cs"
rewardedAd = new RewardedAd();
rewardedAd.SetListener(rewardedListener);
rewardedAd.Load(rewardedRequest);
```
6. **Show ad**. At the impression opportunity moment, you need to check if the BidMachine ad is ready or not.
If BidMachine Rewarded Ad wasn't loaded successfully you need to call IronSource interstitial show method.
```java title="MyClass.java"
if (rewardedAd != null
&& rewardedAd.canShow()
&& rewardedAd.getAuctionResult() != null
&& rewardedAd.getAuctionResult().getPrice() >= ironSourcePrice) {
rewardedAd.show();
} else {
IronSource.showRewardedVideo();
}
```
```swift title="MyClass.swift"
if let rewarded = rewarded, rewarded.canShow, rewarded.auctionInfo.price >= ironSourcePrice {
rewarded.presentAd()
} else {
IronSource.showRewardedVideo(with: self)
}
```
```csharp title="MyClass.cs"
if (rewardedAd.CanShow() && bidmachineRewardedPrice > ironSourceRewarded)
{
rewardedAd.Show();
}
else
{
IronSource.Agent.showRewardedVideo();
}
```
7. _Optional_. For the PDB auction, you might want to implement loading timeout logic.
We recommend adding at least **30 seconds** loading timeout.
Full Rewarded PDB auction integration sample:
```java title="MyClass.java"
private void loadRewarded() {
IronSource.loadRewardedVideo();
}
private void loadBidMachineRewarded(@Nullable AdInfo adInfo) {
if (rewardedAd != null) {
rewardedAd.destroy();
}
RewardedRequest.Builder requestBuilder = new RewardedRequest.Builder();
if (adInfo != null) {
// Get revenue from IronSource and convert it to CPM
ironSourcePrice = adInfo.getRevenue() * 1000
// Calculate price floor
double price = ironSourcePrice + 0.01;
PriceFloorParams priceFloorParams = new PriceFloorParams()
.addPriceFloor(price);
requestBuilder.setPriceFloorParams(priceFloorParams);
}
CustomParams customParams = new CustomParams()
.addParam("mediation_mode", "pdb_is");
requestBuilder.setCustomParams(customParams);
rewardedAd = new RewardedAd(context)
.setListener(new BidMachineRewardedListener())
.load(requestBuilder.build());
}
private void onLoadRewardedCompleted() {
// Handling the end of loading
}
private void showRewarded() {
if (rewardedAd != null
&& rewardedAd.canShow()
&& rewardedAd.getAuctionResult() != null
&& rewardedAd.getAuctionResult().getPrice() >= ironSourcePrice) {
rewardedAd.show();
} else {
IronSource.showRewardedVideo();
}
}
private class IronSourceRewardedManualListener implements LevelPlayRewardedVideoManualListener {
@Override
public void onAdReady(AdInfo adInfo) {
loadBidMachineRewarded(adInfo);
}
@Override
public void onAdLoadFailed(IronSourceError ironSourceError) {
loadBidMachineRewarded(null);
}
// Other callbacks
}
private class BidMachineRewardedListener implements RewardedListener {
@Override
public void onAdLoaded(@NonNull RewardedAd rewardedAd) {
onLoadRewardedCompleted();
}
@Override
public void onAdLoadFailed(@NonNull RewardedAd rewardedAd, @NonNull BMError bmError) {
onLoadRewardedCompleted();
}
// Other callbacks
}
```
```swift title="MyClass.swift"
final class ViewController: UIViewController {
private var rewarded: BidMachineRewarded?
private var ironSourcePrice: Double = 0
override func viewDidLoad() {
super.viewDidLoad()
// Set delegate if needed
// IronSource.setLevelPlayInterstitialDelegate(self)
loadIronSourceRewardedAd()
}
private func loadIronSourceRewardedAd() {
IronSource.loadRewardedVideo()
}
private func loadBidMachineRewarded(_ adInfo: ISAdInfo?) throws {
let configuration = try BidMachineSdk.shared.requestConfiguration(.rewarded)
if let adInfo = adInfo {
ironSourcePrice = adInfo.revenue.doubleValue * 1000
let priceFloor = ironSourcePrice + 0.01
configuration.populate {
$0.appendPriceFloor(priceFloor, "Placement-\(configuration.placement.name)")
}
}
configuration.populate {
$0.withCustomParameters(["mediation_mode": "pdb_is"])
}
BidMachineSdk.shared.rewarded(configuration) { [weak self] rewarded, error in
guard
let self = self,
let rewarded = rewarded
else { return }
rewarded.controller = self
rewarded.delegate = self
self.rewarded = rewarded
rewarded.loadAd()
}
}
private func showInterstitial() {
if let rewarded = rewarded, rewarded.canShow, rewarded.auctionInfo.price >= ironSourcePrice {
rewarded.presentAd()
} else {
IronSource.showRewardedVideo(with: self)
}
}
}
extension ViewController: LevelPlayRewardedVideoManualDelegate {
func didLoad(with adInfo: ISAdInfo!) {
try? loadBidMachineRewarded(adInfo)
}
func didFailToLoadWithError(_ error: (any Error)!) {
try? loadBidMachineRewarded(nil)
}
func didOpen(with adInfo: ISAdInfo!) {}
func didShow(with adInfo: ISAdInfo!) {}
func didFailToShowWithError(_ error: (any Error)!, andAdInfo adInfo: ISAdInfo!) {}
func didClose(with adInfo: ISAdInfo!) {}
func didReceiveReward(forPlacement placementInfo: ISPlacementInfo!, with adInfo: ISAdInfo!) {}
func didClick(_ placementInfo: ISPlacementInfo!, with adInfo: ISAdInfo!) {}
}
extension ViewController: BidMachineAdDelegate {
func didLoadAd(_ ad: any BidMachine.BidMachineAdProtocol) {}
func didFailLoadAd(_ ad: any BidMachine.BidMachineAdProtocol, _ error: any Error) {}
}
```
```csharp title="MyClass.cs"
public static double bidmachineRewardedPrice;
public double ironSourceRewarded;
public CustomParams customParams;
public void LoadRewarded()
{
IronSource.Agent.loadRewardedVideo();
}
public void LoadBidMachineRewardedPDB(IronSourceAdInfo adInfo)
{
if (rewardedRequest != null)
{
rewardedAd.SetListener(null);
rewardedAd.Destroy();
rewardedAd = null;
rewardedRequest = null;
}
customParams = new CustomParams();
customParams.AddParam("mediation_mode", "pdb_is");
double revenue = adInfo.revenue ?? 0.0;
priceFloorParams = new PriceFloorParams();
priceFloorParams.AddPriceFloor("pdb_is_rewarded", revenue*1000+0.1);
rewardedRequest = new RewardedRequest.Builder()
.SetAdContentType(AdContentType.All)
.SetPriceFloorParams(priceFloorParams)
// .SetTargetingParams(targetingParams)
// .SetPlacementId("placement_rewardedRequest")
// .SetLoadingTimeOut(10 * 1000)
// .SetBidPayload("123")
// .SetNetworks("admob")
.SetCustomParams(customParams)
.SetListener(rewardedRequestListener)
.Build();
if (rewardedAd != null)
{
rewardedAd.SetListener(null);
rewardedAd.Destroy();
rewardedAd = null;
}
rewardedAd = new RewardedAd();
rewardedAd.SetListener(rewardedListener);
rewardedAd.Load(rewardedRequest);
}
public void ShowRewarded()
{
if (rewardedAd.CanShow() && bidmachineRewardedPrice > ironSourceRewarded)
{
rewardedAd.Show();
}
else
{
IronSource.Agent.showRewardedVideo();
}
}
// ironSource rewarded callbacks
public void RewardedVideoOnAdReadyEvent(IronSourceAdInfo adInfo)
{
LoadBidMachineRewardedPDB(adInfo);
ironSourceRewarded = adInfo.revenue ?? 0.0
}
public void RewardedVideoOnAdLoadFailed(IronSourceError ironSourceError)
{
// Load BidMachine ad without postbid
LoadBidMachineRewardedAd();
}
public void RewardedVIdeolOnAdClosedEvent(IronSourceAdInfo adInfo)
{
IronSource.Agent.loadRewardedVideo();
}
// Other callback
//BidMachine rewarded callbacks
private class RewardedListener : IRewardedAdListener
{
public void onAdClosed(IRewardedAd ad, bool finished)
{
IronSource.Agent.loadInterstitial();
}
// Other callbacks
}
//BidMachine interstitial request callbacks
private class RewardedRequestListener : IAdRequestListener
{
public void onRequestExpired(IAdRequest request)
{
Debug.Log("BidMachine: RewardedRequest: OnAdRequestExpired");
}
public void onRequestFailed(IAdRequest request, BMError error)
{
Debug.Log($"BidMachine: RewardedRequest: OnAdRequestFailed");
}
public void onRequestSuccess(IAdRequest request, string auctionResult)
{
Debug.Log($"BidMachine: RewardedRequest: OnAdRequestSuccess");
BidMachineAdInfo bidMachineAdInfoinfo = JsonUtility.FromJson(auctionResult);
Debug.Log($"/* REWARDED PRICE */" + bidMachineAdInfoinfo.price);
bidmachineRewardedPrice = bidMachineAdInfoinfo.price;
}
}
public class BidMachineAdInfo
{
public string demandSource;
public string creativeID;
public string bidID;
public string cID;
public double price;
public string dealID;
}
```
---
## Unity LevelPlay First Look
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
## How to integrate BidMachine with Unity LevelPlay using First Look
First Look is an integration method where BidMachine is requested first, and based on the auction result, the app decides whether to proceed with a LevelPlay auction. This approach optimizes ad revenue by adding a competitive Bidmachine auction layer that helps capture higher CPMs and better fill rate.
### Integration Flow
```mermaid
flowchart TD
A[Request BidMachine ad] --> B{BidMachine response}
B -->|Did Load| C[Read customParameters]
B -->|Did Fail| D[Request LevelPlay ad without pricefloor]
C --> E{Skip next auction?}
E -->|Yes| F[Show BidMachine ad]
E -->|No| G[Request LevelPlay adwith price floor]
G --> I{LevelPlay ad successfully loaded?}
I -->|Yes| J[Notify BidMachine lossShow LevelPlay ad]
I -->|No| K[Notify BidMachine winShow BidMachine ad]
D --> M{LevelPlay successfully loaded?}
M -->|Yes| N[Show LevelPlay ad]
M -->|No| O[Repeat an auction]
```
### Integration Steps
1. **Request ad from BidMachine SDK** using the general request flow.
2. **Receive callback** - either `didLoad` or `didFail`.
3. **If `didLoad` triggered:**
- Read `AuctionInfo` object's `customParameters` map.
- Extract two values:
- `"fl_skip"` - boolean flag indicating whether to skip LevelPlay auction;
- `"fl_pf"` - price floor for the LevelPlay auction (CPM value).
4. **If `didFail` triggered:**
- Proceed directly to request LevelPlay ad.
5. **Request LevelPlay ad**:
- Skip if `fl_skip` is `true`.
- Otherwise, request with the price floor from BidMachine's `"fl_pf"` parameter.
6. **On impression moment, check which ad to show:**
- If LevelPlay ad is ready, show LevelPlay ad and notify BidMachine about loss.
- If LevelPlay ad was not loaded, show BidMachine ad (if available) and notify BidMachine about win.
7. **Show the selected ad** and handle all required callbacks.
For detailed BidMachine SDK integration, refer to [BidMachine Developers Documentation](https://developers.bidmachine.io). For LevelPlay SDK integration, refer to [LevelPlay Documentation](https://docs.unity.com/en-us/grow/levelplay/sdk).
### Setup
You need to add both LevelPlay and BidMachine SDK into your project:
```groovy title="build.gradle"
repositories {
google()
mavenCentral()
maven {
url "https://artifactory.bidmachine.io/bidmachine"
}
}
dependencies {
// LevelPlay SDK
implementation "com.unity3d.ads-mediation:mediation-sdk:9.1.0"
// BidMachine SDK
implementation "io.bidmachine:ads:3.5.0"
}
```
```ruby title="Podfile"
pod 'IronSourceSDK', '~> 9.1.0.0'
pod 'BidMachine', '~> 3.5.0'
```
### Initialization
BidMachine SDK should be properly configured and initialized before LevelPlay SDK initialization.
```kotlin title="FirstLookInitialization.kt"
fun initializeNetworks(context: Context) {
// 1. Prepare BidMachine environment - GDPR, CCPA, GPP, Coppa, test mode, etc...
/**
BidMachine.setLoggingEnabled(true)
*/
// 2. Initialize BidMachine
BidMachine.initialize(context, "")
// 3. Prepare LevelPlay environment - GDPR, CCPA, Coppa, etc...
/**
https://developers.is.com/ironsource-mobile/android/android-sdk/
*/
// 4. Initialize LevelPlay
/**
https://developers.is.com/ironsource-mobile/android/android-sdk/
*/
val initRequestBuilder = LevelPlayInitRequest.Builder("")
initRequestBuilder.withUserId("USER_ID") // Optional
val initRequest = initRequestBuilder.build()
LevelPlay.init(context, initRequest, object : LevelPlayInitListener {
override fun onInitFailed(error: LevelPlayInitError) {
// Initialization failed - recommended to retry
}
override fun onInitSuccess(configuration: LevelPlayConfiguration) {
// Initialization successful - start loading ads
}
})
}
```
```swift title="FirstLookInitialization.swift"
func initializeNetworks() {
// 1. Prepare BidMachine environment - GDPR, CCPA, GPP, Coppa, test mode, etc...
/**
BidMachineSdk.shared.populate {
$0.withLoggingMode(true)
}
*/
// 2. Initialize BidMachine
BidMachineSdk.shared.initializeSdk("")
// 3. Prepare LevelPlay environment - GDPR, CCPA, Coppa, etc...
/**
https://developers.is.com/ironsource-mobile/ios/ios-sdk/
*/
// 4. Initialize LevelPlay
/**
https://developers.is.com/ironsource-mobile/ios/ios-sdk/
*/
let requestBuilder = LPMInitRequestBuilder(appKey: "")
requestBuilder.withUserId("USER_ID") // Optional
let initRequest = requestBuilder.build()
LevelPlay.initWith(initRequest) { configuration, error in
if let error = error {
// Initialization failed - recommended to retry
} else {
// Initialization successful - start loading ads
}
}
}
```
:::warning
The placement capping feature is not available for the First Look integration
:::
### Interstitial
To implement First Look integration for Interstitial Ad:
1. **Load BidMachine Interstitial**
```kotlin title="FirstLookInterstitial.kt"
var skipLevelPlayAuction = false
var bidmachineInterstitialRequest: InterstitialRequest? = null
var bidMachineInterstitial: InterstitialAd? = null
var levelPlayInterstitial: LevelPlayInterstitialAd? = null
var levelPlayInterstitialEcpm = 0.0
fun loadBidMachineInterstitial(context: Context) {
val adPlacementConfig = AdPlacementConfig.interstitialBuilder(AdContentType.All)
.apply {
withCustomParams(CustomParams().apply {
addParam("mediation_mode", "first_look")
})
}
.build()
val interstitialRequest = InterstitialRequest.Builder(adPlacementConfig)
.build()
bidmachineInterstitialRequest = interstitialRequest
bidMachineInterstitial = InterstitialAd(context).apply {
setListener(object : InterstitialListener {})
load(interstitialRequest)
}
}
```
```swift title="FirstLookInterstitial.swift"
var skipLevelPlayAuction = false
var bidMachineInterstitial: BidMachineInterstitial!
var levelPlayInterstitial: LPMInterstitialAd!
var levelPlayInterstitialEcpm: Double = 0
var rootViewController: UIViewController!
func loadBidMachineInterstitial() {
let placement = try? BidMachineSdk.shared.placement(.interstitial) {
$0.withCustomParameters(["mediation_mode": "first_look"])
}
guard let placement else { return }
let request = BidMachineSdk.shared.auctionRequest(placement: placement) { builder in
}
BidMachineSdk.shared.interstitial(request: request) { [weak self] interstitial, error in
guard let self = self, let interstitial = interstitial else { return }
interstitial.controller = self.rootViewController
interstitial.delegate = self
self.bidMachineInterstitial = interstitial
interstitial.loadAd()
}
}
```
2. **Handle BidMachine loading callbacks**
```kotlin title="FirstLookInterstitial.kt"
override fun onAdLoaded(ad: InterstitialAd) {
val auctionResult = ad.auctionResult ?: return
val customParams = auctionResult.customParams
val skipNext = customParams["fl_skip"]?.toBooleanStrictOrNull() ?: false
val priceFloor = customParams["fl_pf"]?.toDoubleOrNull() ?: 0.0
if (skipNext) {
skipLevelPlayAuction = true
// Don't load LevelPlay, BidMachine ad will be used
} else {
loadLevelPlayInterstitial(priceFloor)
}
}
override fun onAdLoadFailed(ad: InterstitialAd, error: BMError) {
// Load LevelPlay as fallback
loadLevelPlayInterstitial(0.0)
}
```
```swift title="FirstLookInterstitial.swift"
func didLoadAd(_ ad: any BidMachineAdProtocol) {
guard let interstitial = ad as? BidMachineInterstitial else { return }
let customParams = interstitial.auctionInfo.customParams
if let skipNext = customParams["fl_skip"] as? String, skipNext == "true" {
skipLevelPlayAuction = true
// Don't load LevelPlay, BidMachine ad will be used
} else if let priceFloorStr = customParams["fl_pf"] as? String,
let priceFloor = Double(priceFloorStr) {
loadLevelPlayInterstitial(priceFloor: priceFloor)
} else {
loadLevelPlayInterstitial(priceFloor: 0)
}
}
func didFailLoadAd(_ ad: any BidMachineAdProtocol, _ error: Error) {
// Load LevelPlay as fallback
loadLevelPlayInterstitial(priceFloor: 0)
}
```
3. **Load LevelPlay Interstitial** with price floor if applicable
```kotlin title="FirstLookInterstitial.kt"
private fun loadLevelPlayInterstitial(priceFloor: Double) {
// Create LevelPlay Interstitial ad object with price floor configuration
val adConfig = LevelPlayInterstitialAd.Config.Builder()
.setBidFloor(priceFloor) // Set dynamic price floor from BidMachine
.build()
val interstitialAd = LevelPlayInterstitialAd("", adConfig)
// Set listener
interstitialAd.setListener(object : LevelPlayInterstitialAdListener {
override fun onAdLoaded(adInfo: LevelPlayAdInfo) {
// ad is ready, now you can show it
levelPlayInterstitialEcpm = adInfo.revenue * 1000.0
}
override fun onAdLoadFailed(error: LevelPlayAdError) {}
override fun onAdDisplayed(adInfo: LevelPlayAdInfo) {}
override fun onAdDisplayFailed(error: LevelPlayAdError, adInfo: LevelPlayAdInfo) {}
override fun onAdClicked(adInfo: LevelPlayAdInfo) {}
override fun onAdClosed(adInfo: LevelPlayAdInfo) {}
override fun onAdInfoChanged(adInfo: LevelPlayAdInfo) {}
})
levelPlayInterstitial = interstitialAd
// Load the ad
interstitialAd.loadAd()
}
```
```swift title="FirstLookInterstitial.swift"
private func loadLevelPlayInterstitial(priceFloor: Double) {
// Create LevelPlay Interstitial ad object with price floor configuration
let configBuilder = LPMInterstitialAdConfigBuilder()
configBuilder.set(bidFloor: NSNumber(value: priceFloor)) // Set dynamic price floor from BidMachine
let adConfig = configBuilder.build()
let interstitialAd = LPMInterstitialAd(adUnitId: "", config: adConfig)
// Set delegate
interstitialAd.setDelegate(self)
self.levelPlayInterstitial = interstitialAd
// Load the ad
interstitialAd.loadAd()
}
func didLoadAd(with adInfo: LPMAdInfo) {
// ad is ready, now you can show it
self.levelPlayInterstitialEcpm = adInfo.revenue.doubleValue * 1000
}
func didFailToLoadAd(withAdUnitId adUnitId: String, error: any Error) { }
func didDisplayAd(with adInfo: LPMAdInfo) { }
```
4. **Show the appropriate ad and notify BidMachine**
```kotlin title="FirstLookInterstitial.kt"
private fun showInterstitial(activity: Activity) {
val canShowBidMachine = bidMachineInterstitial?.canShow() == true
val canShowLevelPlay = levelPlayInterstitial?.isAdReady == true
when {
skipLevelPlayAuction && canShowBidMachine -> {
// Only BidMachine ad available
bidmachineInterstitialRequest?.notifyMediationWin()
bidMachineInterstitial?.show()
}
canShowLevelPlay -> {
// LevelPlay wins
bidmachineInterstitialRequest?.notifyMediationLoss("levelplay", levelPlayInterstitialEcpm)
levelPlayInterstitial?.showAd(activity)
}
canShowBidMachine -> {
// BidMachine wins (LevelPlay not ready)
bidmachineInterstitialRequest?.notifyMediationWin()
bidMachineInterstitial?.show()
}
}
}
```
```swift title="FirstLookInterstitial.swift"
private func showInterstitial() {
if skipLevelPlayAuction {
// Only BidMachine ad available
if let interstitial = bidMachineInterstitial, interstitial.canShow {
BidMachineSdk.shared.notifyMediationWin(interstitial)
interstitial.presentAd()
}
return
}
if let levelPlayInterstitial = levelPlayInterstitial, levelPlayInterstitial.isAdReady() {
// LevelPlay wins
if let bidMachineInterstitial = bidMachineInterstitial {
BidMachineSdk.shared.notifyMediationLoss("levelplay", levelPlayInterstitialEcpm, bidMachineInterstitial)
}
levelPlayInterstitial.showAd(viewController: rootViewController, placementName: nil)
} else if let interstitial = bidMachineInterstitial, interstitial.canShow {
// BidMachine wins
BidMachineSdk.shared.notifyMediationWin(interstitial)
interstitial.presentAd()
}
}
```
Complete Interstitial Implementation Example (Click to expand)
```kotlin title="FirstLookInterstitialManager.kt"
class FirstLookInterstitialManager(private val context: Context) {
private var skipLevelPlayAuction = false
private var bidmachineInterstitialRequest: InterstitialRequest? = null
private var bidMachineInterstitial: InterstitialAd? = null
private var levelPlayInterstitial: LevelPlayInterstitialAd? = null
private var levelPlayInterstitialEcpm = 0.0
fun loadBidMachineInterstitial() {
val adPlacementConfig = AdPlacementConfig.interstitialBuilder(AdContentType.All)
.apply {
withCustomParams(CustomParams().apply {
addParam("mediation_mode", "first_look")
})
}
.build()
val interstitialRequest = InterstitialRequest.Builder(adPlacementConfig)
.build()
bidmachineInterstitialRequest = interstitialRequest
bidMachineInterstitial = InterstitialAd(context).apply {
setListener(object : InterstitialListener {
override fun onAdLoaded(ad: InterstitialAd) {
val auctionResult = ad.auctionResult ?: return
val customParams = auctionResult.customParams
val skipNext = customParams["fl_skip"]?.toBooleanStrictOrNull() ?: false
val priceFloor = customParams["fl_pf"]?.toDoubleOrNull() ?: 0.0
if (skipNext) {
skipLevelPlayAuction = true
// Don't load LevelPlay, BidMachine ad will be used
} else {
loadLevelPlayInterstitial(priceFloor)
}
}
override fun onAdLoadFailed(ad: InterstitialAd, error: BMError) {
// Load LevelPlay as fallback
loadLevelPlayInterstitial(0.0)
}
override fun onAdImpression(ad: InterstitialAd) {}
override fun onAdShowFailed(ad: InterstitialAd, error: BMError) {}
override fun onAdClicked(ad: InterstitialAd) {}
override fun onAdExpired(ad: InterstitialAd) {}
override fun onAdClosed(ad: InterstitialAd, finished: Boolean) {}
})
load(bidmachineInterstitialRequest)
}
}
private fun loadLevelPlayInterstitial(priceFloor: Double) {
// Create LevelPlay Interstitial ad object with price floor configuration
val adConfig = LevelPlayInterstitialAd.Config.Builder()
.setBidFloor(priceFloor) // Set dynamic price floor from BidMachine
.build()
val interstitialAd = LevelPlayInterstitialAd("", adConfig)
// Set listener
interstitialAd.setListener(object : LevelPlayInterstitialAdListener {
override fun onAdLoaded(adInfo: LevelPlayAdInfo) {
// ad is ready, now you can show it
levelPlayInterstitialEcpm = adInfo.revenue * 1000.0
}
override fun onAdLoadFailed(error: LevelPlayAdError) {}
override fun onAdDisplayed(adInfo: LevelPlayAdInfo) {}
override fun onAdDisplayFailed(error: LevelPlayAdError, adInfo: LevelPlayAdInfo) {}
override fun onAdClicked(adInfo: LevelPlayAdInfo) {}
override fun onAdClosed(adInfo: LevelPlayAdInfo) {}
override fun onAdInfoChanged(adInfo: LevelPlayAdInfo) {}
})
levelPlayInterstitial = interstitialAd
// Load the ad
interstitialAd.loadAd()
}
fun showInterstitial(activity: Activity) {
val canShowBidMachine = bidMachineInterstitial?.canShow() == true
val canShowLevelPlay = levelPlayInterstitial?.isAdReady == true
when {
skipLevelPlayAuction && canShowBidMachine -> {
// Only BidMachine ad available
bidmachineInterstitialRequest?.notifyMediationWin()
bidMachineInterstitial?.show()
}
canShowLevelPlay -> {
// LevelPlay wins
bidmachineInterstitialRequest?.notifyMediationLoss("levelplay", levelPlayInterstitialEcpm)
levelPlayInterstitial?.showAd(activity)
}
canShowBidMachine -> {
// BidMachine wins (LevelPlay not ready)
bidmachineInterstitialRequest?.notifyMediationWin()
bidMachineInterstitial?.show()
}
}
}
}
```
```swift title="FirstLookInterstitialManager.swift"
import BidMachine
import IronSource
final class FirstLookInterstitialManager: NSObject {
var skipLevelPlayAuction = false
var bidMachineInterstitial: BidMachineInterstitial!
var levelPlayInterstitial: LPMInterstitialAd!
var levelPlayInterstitialEcpm: Double = 0
let rootViewController: UIViewController
init(rootViewController: UIViewController) {
self.rootViewController = rootViewController
}
func loadAd() {
loadBidMachineInterstitial()
}
func loadBidMachineInterstitial() {
let placement = try? BidMachineSdk.shared.placement(.interstitial) {
$0.withCustomParameters(["mediation_mode": "first_look"])
}
guard let placement else { return }
let request = BidMachineSdk.shared.auctionRequest(placement: placement) { builder in
}
BidMachineSdk.shared.interstitial(request: request) { [weak self] interstitial, error in
guard let self = self, let interstitial = interstitial else { return }
interstitial.controller = self.rootViewController
interstitial.delegate = self
self.bidMachineInterstitial = interstitial
interstitial.loadAd()
}
}
private func showInterstitial() {
if skipLevelPlayAuction {
// Only BidMachine ad available
if let interstitial = bidMachineInterstitial, interstitial.canShow {
BidMachineSdk.shared.notifyMediationWin(interstitial)
interstitial.presentAd()
}
return
}
if let levelPlayInterstitial = levelPlayInterstitial, levelPlayInterstitial.isAdReady() {
// LevelPlay wins
if let bidMachineInterstitial = bidMachineInterstitial {
BidMachineSdk.shared.notifyMediationLoss("levelplay", levelPlayInterstitialEcpm, bidMachineInterstitial)
}
levelPlayInterstitial.showAd(viewController: rootViewController, placementName: nil)
} else if let interstitial = bidMachineInterstitial, interstitial.canShow {
// BidMachine wins
BidMachineSdk.shared.notifyMediationWin(interstitial)
interstitial.presentAd()
}
}
private func loadLevelPlayInterstitial(priceFloor: Double) {
// Create LevelPlay Interstitial ad object with price floor configuration
let configBuilder = LPMInterstitialAdConfigBuilder()
configBuilder.set(bidFloor: NSNumber(value: priceFloor)) // Set dynamic price floor from BidMachine
let adConfig = configBuilder.build()
let interstitialAd = LPMInterstitialAd(adUnitId: "", config: adConfig)
// Set delegate
interstitialAd.setDelegate(self)
self.levelPlayInterstitial = interstitialAd
// Load the ad
interstitialAd.loadAd()
}
}
extension FirstLookInterstitialManager: BidMachineAdDelegate {
func didLoadAd(_ ad: any BidMachineAdProtocol) {
guard let interstitial = ad as? BidMachineInterstitial else { return }
let customParams = interstitial.auctionInfo.customParams
if let skipNext = customParams["fl_skip"] as? String, skipNext == "true" {
skipLevelPlayAuction = true
// Don't load LevelPlay, BidMachine ad will be used
} else if let priceFloorStr = customParams["fl_pf"] as? String,
let priceFloor = Double(priceFloorStr) {
loadLevelPlayInterstitial(priceFloor: priceFloor)
} else {
loadLevelPlayInterstitial(priceFloor: 0)
}
}
func didFailLoadAd(_ ad: any BidMachineAdProtocol, _ error: Error) {
// Load LevelPlay as fallback
loadLevelPlayInterstitial(priceFloor: 0)
}
func didPresentAd(_ ad: any BidMachineAdProtocol) {}
func didDismissAd(_ ad: any BidMachineAdProtocol) {}
func didFailPresentAd(_ ad: any BidMachineAdProtocol, _ error: any Error) {}
func willPresentScreen(_ ad: any BidMachineAdProtocol) {}
func didDismissScreen(_ ad: any BidMachineAdProtocol) {}
func didUserInteraction(_ ad: any BidMachineAdProtocol) {}
func didExpired(_ ad: any BidMachineAdProtocol) {}
func didTrackImpression(_ ad: any BidMachineAdProtocol) {}
func didTrackInteraction(_ ad: any BidMachineAdProtocol) {}
}
extension FirstLookInterstitialManager: LPMInterstitialAdDelegate {
func didLoadAd(with adInfo: LPMAdInfo) {
// ad is ready, now you can show it
self.levelPlayInterstitialEcpm = adInfo.revenue.doubleValue * 1000
}
func didFailToLoadAd(withAdUnitId adUnitId: String, error: any Error) {}
func didDisplayAd(with adInfo: LPMAdInfo) {}
func didFailToDisplayAd(with adInfo: LPMAdInfo, error: Error) {}
func didClickAd(with adInfo: LPMAdInfo) {}
func didCloseAd(with adInfo: LPMAdInfo) {}
}
```
### Rewarded
To implement First Look integration for Rewarded Ad:
1. **Load BidMachine Rewarded**
```kotlin title="FirstLookRewarded.kt"
fun loadBidMachineRewarded() {
val adPlacementConfig = AdPlacementConfig.rewardedBuilder(AdContentType.All)
.apply {
withCustomParams(CustomParams().apply {
addParam("mediation_mode", "first_look")
})
}
.build()
val rewardedRequest = RewardedRequest.Builder(adPlacementConfig)
.build()
bidmachineRewardedRequest = rewardedRequest
bidMachineRewarded = RewardedAd(context).apply {
setListener(object : RewardedListener {})
load(bidmachineRewardedRequest)
}
}
```
```swift title="FirstLookRewarded.swift"
var skipLevelPlayAuction = false
var bidMachineRewarded: BidMachineRewarded!
var levelPlayRewarded: LPMRewardedAd!
var levelPlayRewardedEcpm: Double = 0
var rootViewController: UIViewController!
func loadBidMachineRewarded() {
let placement = try? BidMachineSdk.shared.placement(.rewarded) {
$0.withCustomParameters(["mediation_mode": "first_look"])
}
guard let placement else { return }
let request = BidMachineSdk.shared.auctionRequest(placement: placement) { builder in
}
BidMachineSdk.shared.rewarded(request: request) { [weak self] rewarded, error in
guard let self = self, let rewarded = rewarded else { return }
rewarded.controller = self.rootViewController
rewarded.delegate = self
self.bidMachineRewarded = rewarded
rewarded.loadAd()
}
}
```
2. **Handle BidMachine loading callbacks**
```kotlin title="FirstLookRewarded.kt"
override fun onAdLoaded(ad: RewardedAd) {
val auctionResult = ad.auctionResult ?: return
val customParams = auctionResult.customParams
val skipNext = customParams["fl_skip"]?.toBooleanStrictOrNull() ?: false
val priceFloor = customParams["fl_pf"]?.toDoubleOrNull() ?: 0.0
if (skipNext) {
skipLevelPlayAuction = true
// Don't load LevelPlay, BidMachine ad will be used
} else {
loadLevelPlayRewarded(priceFloor)
}
}
override fun onAdLoadFailed(ad: RewardedAd, error: BMError) {
// Load LevelPlay as fallback
loadLevelPlayRewarded(0.0)
}
```
```swift title="FirstLookRewarded.swift"
func didLoadAd(_ ad: any BidMachineAdProtocol) {
guard let rewarded = ad as? BidMachineRewarded else { return }
let customParams = rewarded.auctionInfo.customParams
if let skipNext = customParams["fl_skip"] as? String, skipNext == "true" {
skipLevelPlayAuction = true
// Don't load LevelPlay, BidMachine ad will be used
} else if let priceFloorStr = customParams["fl_pf"] as? String,
let priceFloor = Double(priceFloorStr) {
loadLevelPlayRewarded(priceFloor: priceFloor)
} else {
loadLevelPlayRewarded(priceFloor: 0)
}
}
func didFailLoadAd(_ ad: any BidMachineAdProtocol, _ error: Error) {
// Load LevelPlay as fallback
loadLevelPlayRewarded(priceFloor: 0)
}
```
3. **Load LevelPlay Rewarded** with price floor if applicable
```kotlin title="FirstLookRewarded.kt"
private fun loadLevelPlayRewarded(priceFloor: Double) {
// Create LevelPlay Rewarded ad object with price floor configuration
val adConfig = LevelPlayRewardedAd.Config.Builder()
.setBidFloor(priceFloor) // Set dynamic price floor from BidMachine
.build()
val rewardedAd = LevelPlayRewardedAd("", adConfig)
// Set listener
rewardedAd.setListener(object : LevelPlayRewardedAdListener {
override fun onAdLoaded(adInfo: LevelPlayAdInfo) {
// ad is ready, now you can show it
levelPlayRewardedEcpm = adInfo.revenue * 1000.0
}
override fun onAdLoadFailed(error: LevelPlayAdError) {}
override fun onAdDisplayed(adInfo: LevelPlayAdInfo) {}
override fun onAdDisplayFailed(error: LevelPlayAdError, adInfo: LevelPlayAdInfo) {}
override fun onAdClicked(adInfo: LevelPlayAdInfo) {}
override fun onAdClosed(adInfo: LevelPlayAdInfo) {}
override fun onAdInfoChanged(adInfo: LevelPlayAdInfo) {}
override fun onAdRewarded(reward: LevelPlayReward, adInfo: LevelPlayAdInfo) {}
})
levelPlayRewarded = rewardedAd
// Load the ad
rewardedAd.loadAd()
}
```
```swift title="FirstLookRewarded.swift"
private func loadLevelPlayRewarded(priceFloor: Double) {
// Create LevelPlay Rewarded ad object with price floor configuration
let configBuilder = LPMRewardedAdConfigBuilder()
configBuilder.set(bidFloor: NSNumber(value: priceFloor)) // Set dynamic price floor from BidMachine
let adConfig = configBuilder.build()
let rewardedAd = LPMRewardedAd(adUnitId: "", config: adConfig)
// Set delegate
rewardedAd.setDelegate(self)
self.levelPlayRewarded = rewardedAd
// Load the ad
rewardedAd.loadAd()
}
func didLoadAd(with adInfo: LPMAdInfo) {
// ad is ready, now you can show it
self.levelPlayRewardedEcpm = adInfo.revenue.doubleValue * 1000
}
func didFailToLoadAd(withAdUnitId adUnitId: String, error: any Error) { }
func didDisplayAd(with adInfo: LPMAdInfo) { }
```
4. **Show the appropriate ad and notify BidMachine**
```kotlin title="FirstLookRewarded.kt"
fun showRewarded(activity: Activity) {
val canShowBidMachine = bidMachineRewarded?.canShow() == true
val canShowLevelPlay = levelPlayRewarded?.isAdReady == true
when {
skipLevelPlayAuction && canShowBidMachine -> {
// Only BidMachine ad available
bidmachineRewardedRequest?.notifyMediationWin()
bidMachineRewarded?.show()
}
canShowLevelPlay -> {
// LevelPlay wins
bidmachineRewardedRequest?.notifyMediationLoss("levelplay", levelPlayRewardedEcpm)
levelPlayRewarded?.showAd(activity)
}
canShowBidMachine -> {
// BidMachine wins (LevelPlay not ready)
bidmachineRewardedRequest?.notifyMediationWin()
bidMachineRewarded?.show()
}
}
}
```
```swift title="FirstLookRewarded.swift"
private func showRewarded() {
if skipLevelPlayAuction {
// Only BidMachine ad available
if let rewarded = bidMachineRewarded, rewarded.canShow {
BidMachineSdk.shared.notifyMediationWin(rewarded)
rewarded.presentAd()
}
return
}
if let levelPlayRewarded = levelPlayRewarded, levelPlayRewarded.isAdReady() {
// LevelPlay wins
if let bidMachineRewarded = bidMachineRewarded {
BidMachineSdk.shared.notifyMediationLoss("levelplay", levelPlayRewardedEcpm, bidMachineRewarded)
}
levelPlayRewarded.showAd(viewController: rootViewController, placementName: nil)
} else if let rewarded = bidMachineRewarded, rewarded.canShow {
// BidMachine wins
BidMachineSdk.shared.notifyMediationWin(rewarded)
rewarded.presentAd()
}
}
```
Complete Rewarded Ad Implementation Example (Click to expand)
```kotlin title="FirstLookInterstitialManager.kt"
class FirstLookRewardedManager(private val context: Context) {
private var skipLevelPlayAuction = false
private var bidmachineRewardedRequest: RewardedRequest? = null
private var bidMachineRewarded: RewardedAd? = null
private var levelPlayRewarded: LevelPlayRewardedAd? = null
private var levelPlayRewardedEcpm = 0.0
fun loadBidMachineRewarded() {
val adPlacementConfig = AdPlacementConfig.rewardedBuilder(AdContentType.All)
.apply {
withCustomParams(CustomParams().apply {
addParam("mediation_mode", "first_look")
})
}
.build()
val rewardedRequest = RewardedRequest.Builder(adPlacementConfig)
.build()
bidmachineRewardedRequest = rewardedRequest
bidMachineRewarded = RewardedAd(context).apply {
setListener(object : RewardedListener {
override fun onAdLoaded(ad: RewardedAd) {
val auctionResult = ad.auctionResult ?: return
val customParams = auctionResult.customParams
val skipNext = customParams["fl_skip"]?.toBooleanStrictOrNull() ?: false
val priceFloor = customParams["fl_pf"]?.toDoubleOrNull() ?: 0.0
if (skipNext) {
skipLevelPlayAuction = true
// Don't load LevelPlay, BidMachine ad will be used
} else {
loadLevelPlayRewarded(priceFloor)
}
}
override fun onAdLoadFailed(ad: RewardedAd, error: BMError) {
// Load LevelPlay as fallback
loadLevelPlayRewarded(0.0)
}
override fun onAdImpression(ad: RewardedAd) {}
override fun onAdShowFailed(ad: RewardedAd, error: BMError) {}
override fun onAdClicked(ad: RewardedAd) {}
override fun onAdExpired(ad: RewardedAd) {}
override fun onAdClosed(ad: RewardedAd, finished: Boolean) {}
override fun onAdRewarded(ad: RewardedAd) {}
})
load(bidmachineRewardedRequest)
}
}
private fun loadLevelPlayRewarded(priceFloor: Double) {
// Create LevelPlay Rewarded ad object with price floor configuration
val adConfig = LevelPlayRewardedAd.Config.Builder()
.setBidFloor(priceFloor) // Set dynamic price floor from BidMachine
.build()
val rewardedAd = LevelPlayRewardedAd("", adConfig)
// Set listener
rewardedAd.setListener(object : LevelPlayRewardedAdListener {
override fun onAdLoaded(adInfo: LevelPlayAdInfo) {
// ad is ready, now you can show it
levelPlayRewardedEcpm = adInfo.revenue * 1000.0
}
override fun onAdLoadFailed(error: LevelPlayAdError) {}
override fun onAdDisplayed(adInfo: LevelPlayAdInfo) {}
override fun onAdDisplayFailed(error: LevelPlayAdError, adInfo: LevelPlayAdInfo) {}
override fun onAdClicked(adInfo: LevelPlayAdInfo) {}
override fun onAdClosed(adInfo: LevelPlayAdInfo) {}
override fun onAdInfoChanged(adInfo: LevelPlayAdInfo) {}
override fun onAdRewarded(reward: LevelPlayReward, adInfo: LevelPlayAdInfo) {}
})
levelPlayRewarded = rewardedAd
// Load the ad
rewardedAd.loadAd()
}
fun showRewarded(activity: Activity) {
val canShowBidMachine = bidMachineRewarded?.canShow() == true
val canShowLevelPlay = levelPlayRewarded?.isAdReady == true
when {
skipLevelPlayAuction && canShowBidMachine -> {
// Only BidMachine ad available
bidmachineRewardedRequest?.notifyMediationWin()
bidMachineRewarded?.show()
}
canShowLevelPlay -> {
// LevelPlay wins
bidmachineRewardedRequest?.notifyMediationLoss("levelplay", levelPlayRewardedEcpm)
levelPlayRewarded?.showAd(activity)
}
canShowBidMachine -> {
// BidMachine wins (LevelPlay not ready)
bidmachineRewardedRequest?.notifyMediationWin()
bidMachineRewarded?.show()
}
}
}
}
```
```swift title="FirstLookRewardedManager.swift"
import BidMachine
import IronSource
final class FirstLookRewardedManager: NSObject {
var skipLevelPlayAuction = false
var bidMachineRewarded: BidMachineRewarded!
var levelPlayRewarded: LPMRewardedAd!
var levelPlayRewardedEcpm: Double = 0
let rootViewController: UIViewController
init(rootViewController: UIViewController) {
self.rootViewController = rootViewController
}
func loadAd() {
loadBidMachineRewarded()
}
func loadBidMachineRewarded() {
let placement = try? BidMachineSdk.shared.placement(.rewarded) {
$0.withCustomParameters(["mediation_mode": "first_look"])
}
guard let placement else { return }
let request = BidMachineSdk.shared.auctionRequest(placement: placement) { builder in
}
BidMachineSdk.shared.rewarded(request: request) { [weak self] rewarded, error in
guard let self = self, let rewarded = rewarded else { return }
rewarded.controller = self.rootViewController
rewarded.delegate = self
self.bidMachineRewarded = rewarded
rewarded.loadAd()
}
}
private func showRewarded() {
if skipLevelPlayAuction {
// Only BidMachine ad available
if let rewarded = bidMachineRewarded, rewarded.canShow {
BidMachineSdk.shared.notifyMediationWin(rewarded)
rewarded.presentAd()
}
return
}
if let levelPlayRewarded = levelPlayRewarded, levelPlayRewarded.isAdReady() {
// LevelPlay wins
if let bidMachineRewarded = bidMachineRewarded {
BidMachineSdk.shared.notifyMediationLoss("levelplay", levelPlayRewardedEcpm, bidMachineRewarded)
}
levelPlayRewarded.showAd(viewController: rootViewController, placementName: nil)
} else if let rewarded = bidMachineRewarded, rewarded.canShow {
// BidMachine wins
BidMachineSdk.shared.notifyMediationWin(rewarded)
rewarded.presentAd()
}
}
private func loadLevelPlayRewarded(priceFloor: Double) {
// Create LevelPlay Rewarded ad object with price floor configuration
let configBuilder = LPMRewardedAdConfigBuilder()
configBuilder.set(bidFloor: NSNumber(value: priceFloor)) // Set dynamic price floor from BidMachine
let adConfig = configBuilder.build()
let rewardedAd = LPMRewardedAd(adUnitId: "", config: adConfig)
// Set delegate
rewardedAd.setDelegate(self)
self.levelPlayRewarded = rewardedAd
// Load the ad
rewardedAd.loadAd()
}
}
extension FirstLookRewardedManager: BidMachineAdDelegate {
func didLoadAd(_ ad: any BidMachineAdProtocol) {
guard let rewarded = ad as? BidMachineRewarded else { return }
let customParams = rewarded.auctionInfo.customParams
if let skipNext = customParams["fl_skip"] as? String, skipNext == "true" {
skipLevelPlayAuction = true
// Don't load LevelPlay, BidMachine ad will be used
} else if let priceFloorStr = customParams["fl_pf"] as? String,
let priceFloor = Double(priceFloorStr) {
loadLevelPlayRewarded(priceFloor: priceFloor)
} else {
loadLevelPlayRewarded(priceFloor: 0)
}
}
func didFailLoadAd(_ ad: any BidMachineAdProtocol, _ error: Error) {
// Load LevelPlay as fallback
loadLevelPlayRewarded(priceFloor: 0)
}
func didPresentAd(_ ad: any BidMachineAdProtocol) {}
func didDismissAd(_ ad: any BidMachineAdProtocol) {}
func didFailPresentAd(_ ad: any BidMachineAdProtocol, _ error: any Error) {}
func willPresentScreen(_ ad: any BidMachineAdProtocol) {}
func didDismissScreen(_ ad: any BidMachineAdProtocol) {}
func didUserInteraction(_ ad: any BidMachineAdProtocol) {}
func didExpired(_ ad: any BidMachineAdProtocol) {}
func didTrackImpression(_ ad: any BidMachineAdProtocol) {}
func didTrackInteraction(_ ad: any BidMachineAdProtocol) {}
}
extension FirstLookRewardedManager: LPMRewardedAdDelegate {
func didLoadAd(with adInfo: LPMAdInfo) {
// ad is ready, now you can show it
self.levelPlayRewardedEcpm = adInfo.revenue.doubleValue * 1000
}
func didFailToLoadAd(withAdUnitId adUnitId: String, error: any Error) {}
func didDisplayAd(with adInfo: LPMAdInfo) {}
func didFailToDisplayAd(with adInfo: LPMAdInfo, error: Error) {}
func didClickAd(with adInfo: LPMAdInfo) {}
func didCloseAd(with adInfo: LPMAdInfo) {}
func didRewardAd(with adInfo: LPMAdInfo, reward: LPMReward) {}
}
```
## Best Practices
1. **Custom Parameters**: Always add `mediation_mode: "first_look"` to BidMachine requests for proper analytics tracking.
2. **Win/Loss Notifications**: Always notify BidMachine of auction results to maintain proper auction optimization.
3. **Priority Logic**: LevelPlay ad takes priority if it's ready at impression moment; otherwise show BidMachine ad.
4. **Error Handling**: Always implement fallback logic when BidMachine or LevelPlay fail to load.
5. **Timeout**: Consider implementing timeout logic to avoid waiting too long for ad responses.
6. **Dynamic Price Floor**: Use the `Config.Builder().setBidFloor()` API (Android) or `ConfigBuilder.set(bidFloor:)` (iOS) to set dynamic price floors from BidMachine's auction results. This ensures LevelPlay only serves ads that meet or exceed BidMachine's floor price.
7. **Ad Unit API**: LevelPlay SDK 8.5.0+ uses the new Multiple Ad Unit API for both Interstitial and Rewarded ads, providing better control and configuration options including dynamic price floors.
---
## Adapters Compatibility(Max)
import AdapterSelect from '@site/src/components/mdx/adapter-select';
Unity Level Play Adapters for BidMachine Bidding and Waterfall are available for both Android and iOS platforms.
They are distributd as `CocoaPods Pod` for iOS and as `AAR` for Android.
:::note
BidMachine Bidding adapter is maintained by [AppLovin](https://dash.applovin.com/documentation/mediation/max/get-started-with-max).
:::
Below you can find the list of supported versions for BidMachine Bidding adapter.
---
## Bidding Adapter(Android)
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import JavaLabel from '@site/src/components/code-labels/java'
import KotlinLabel from '@site/src/components/code-labels/kotlin'
import SwiftLabel from '@site/src/components/code-labels/swift'
import ObjCLabel from '@site/src/components/code-labels/objc'
BidMachine bidding adapter allows you to use the BidMachine ad platform
within your existing AppLovin MAX mediation.
BidMachine supports banners, MRECs, interstitials and rewarded videos.
[How to Enable BidMachine in AppLovin MAX](/sdk/max/max-console-setup)
## Add the BidMachine Bidding Adapter to Your Build
:::info
Min Android SDK version - 21 (5.0 Lollipop)
:::
To integrate the BidMachine SDK with Gradle, make sure the following Maven URL exists in your `build.gradle`
```groovy title="build.gradle"
repositories {
mavenCentral()
maven {
url "https://artifactory.bidmachine.io/bidmachine"
}
}
```
In your `build.gradle` file add the following dependency which includes the BidMachine adapter for use within AppLovin MAX mediation platform:
```groovy title="build.gradle"
dependencies {
implementation "com.applovin:applovin-sdk:+"
implementation "com.applovin.mediation:bidmachine-adapter:+"
}
```
## Additional Configuration
- [Advanced SDK settings](/sdk/general/android/advanced/)
- [Data Privacy settings](/sdk/general/android/privacy/)
---
## MAX Bidder Specification
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjCLabel from "@site/src/components/code-labels/objc";
## Overview
BidMachine bidding supports [oRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) protocol to receive bids from supply partners and return bid responses. To integrate with BidMachine, the supply partner should integrate BidMachine SDK and the bid request should be compliant with Open RTB 2.5 Spec.
## Protocol
BidMachine service requires HTTP protocol and recommends TLS 1.2 or above.
## Request Regions
BidMachine servers are located in regions: US, EU, APAC. We highly recommend supply partners use the same region for RTB calls to avoid latency.
## Endpoint
EU region: [https://api-eu.bidmachine.io/auction/prebid/applovin](https://api-eu.bidmachine.io/auction/prebid/applovin)
US region: [https://api-us.bidmachine.io/auction/prebid/applovin](https://api-us.bidmachine.io/auction/prebid/applovin)
## Supported Ad Formats
BidMachine only participates in mobile in-app auctions. Supported ad formats are:
- Fullscreen banner (`320x480`; `480x320`; `1024x768`; `768x1024`)
- Small banner (`320x50`; `728x90`)
- Skippable video (`320x480`; `480x320`; `1024x768`; `768x1024`)
- Rewarded video (`320x480`; `480x320`; `1024x768`; `768x1024`)
- Native Ads
## Supported Currency
USD only.
## Supported Auction Type
First-price auction Only.
## Bid Request
BidMachine server only takes one single impression in each bid request.
Key oRTB fields:
- `app.bundle` (required)
- `app.storeurl` (required)
- `app.name` (required)
- `imp.instl` (required)
- `device.os` (required)
- `tmax` (Required and recommended value >1000ms)
A full BidMachine oRTB Bid Request Specification can be checked [here](/sdk/ssp/request/specification).
:::info
1. Partners should share a bid request example that they planning to use for the integration.
2. If partners have their own bid request spec and would like BidMachine to respect, please contact your BidMachine Account Manager.
:::
## Bid Response
BidMachine's bid response adheres to the **Open RTB 2.5** protocol.
### No Bid
To communicate a no-bid response, BidMachine passes an empty response with a status code 204.
### Notifications
We require `win` and `loss` notifications with the appropriate loss codes as defined in oRTB.
oRTB `NURL` and `LURL` are provided in the bid response.
If partners have any customized auction substitution macros, please notify BidMachine to support in the notification URL.
[Response](/sdk/ssp/response/examples) and [Request](/sdk/ssp/request/examples) Examples.
## Adapters
### Android
:::info
BidMachine Android SDK supported started since **v1.9.0**
:::
### Initialization
The initialization should occur once per session.
Partner initializes SDK before requesting ads.
More information [here](/sdk/general/android/overview#initialize-the-sdk).
#### Bid Token
To get a BidToken, please use one of the proposed methods:
}>
```java
// Must be run on background thread
String bidToken = BidMachine.getBidToken(context);
```
}>
```kotlin
val bidToken = BidMachine.getBidToken(context)
```
or
}>
```java
BidMachine.getBidToken(context, new BidTokenCallback() {
@Override
public void onCollected(@NonNull String bidToken) {
// The BidToken will be returned on a background thread
}
});
```
}>
```kotlin
BidMachine.getBidToken(applicationContext) { bidToken ->
// The BidToken will be returned on a background thread
}
```
#### Bid Payload
To set up bid payload for ad request use `setBidPayload` method from `AdRequest` builder according to ad type.
}>
```java
adRequestBuilder.setBidPayload(String);
```
}>
```kotlin
adRequestBuilder.setBidPayload(String)
```
[BidMachine SDK Android BidPayload Examples](https://github.com/bidmachine/BidMachine-Android-BidPayload-demo)
### iOS
:::info
BidMachine iOS SDK supported started since **v1.9.0**
:::
#### Initialization
The initialization should occur once per session.
Partner initializes SDK before requesting ads.
More information [here](/sdk/general/ios/overview#initialization)
### Bid Token
To get a BidToken, please use one of the proposed method: (api available from v1.9.0.0)
```objc
/// Generates bidder token that needs to be included in the server side bid request
@property (copy, nonatomic, readonly, nullable) NSString *biddingToken;
```
Example:
:::note
It is recommended to call the method on the background thread
:::
}>
```objc
NSString *token = BDMSdk.sharedSdk.biddingToken
```
}>
```swift
let token = BDMSdk.shared().biddingToken
```
#### Bid Payload
To set up bid payload for ad request use `setBidPayload` method from `BDMRequest`
}>
```objc
- (void)populateRequest:(BDMRequest *)request {
request.bidPayload = @"Custom payload string";
}
```
}>
```swift
func populate(_ request: BDMRequest) {
request.bidPayload = "Custom payload string"
}
```
[BidMachine SDK IOS BidPayload Examples](https://github.com/bidmachine/BidMachine-IOS-BidPayload-demo)
## Integration Testing
During the development and testing phases, BidMachine encourages you to use test mode to verify your app bidding integration.
Please use the following endpoint to test an S2S integration:
- [https://api-eu.bidmachine.io/auction/prebid/applovin](https://api-eu.bidmachine.io/auction/prebid/applovin)
- [https://api-us.bidmachine.io/auction/prebid/applovin](https://api-us.bidmachine.io/auction/prebid/applovin)
:::warning
Bid floor: should be equal to **0.01**
Test mode should be enabled: `"test": 1`
:::
## Information Collected by SDK
| Device Data | Additional Data |
|----------------------|-----------------------|
| App bundle | SDK name |
| App version | SDK version |
| OS | impdepth |
| OS version | sessionduration |
| Device type | lastbundle |
| Connection type | lastadomain |
| Location Lat | clickrate |
| Location Lon | lastclick |
| Location Type | completionrate |
| Location Accuracy | |
| Location Lastfix | |
| Country | |
| City | |
| Zip | |
| UTC | |
| IFV (iOS Only) | |
| IFA | |
---
## AppLovin MAX First Look
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
## How to integrate BidMachine with AppLovin MAX using First Look
First Look is a pre-mediation layer that evaluates every impression **before** your main mediation (MAX) runs. BidMachine gets the first opportunity to fill with curated, publisher-approved demand. If First Look fills, MAX is not called. If First Look passes, MAX runs exactly as normal.
The auction settings (e.g., which demand sources participate) are configured on the BidMachine backend via **Placement ID**. This means the app-side integration is straightforward — you just need to pass the correct Placement ID when loading a BidMachine ad, and the backend will apply the right auction configuration.
### Integration Flow
```mermaid
flowchart TD
A[App triggers ad request] --> B[Load BidMachine adwith Placement ID]
B --> C{BidMachine response}
C -->|Did Load| D[Show BidMachine ad]
C -->|Did Fail| E[Load AppLovin MAX ad]
E --> F{MAX response}
F -->|Did Load| G[Show MAX ad]
F -->|Did Fail| H[No ad available]
```
### Integration Steps
1. **Configure a Placement ID** in the BidMachine dashboard with the desired auction settings (e.g., curated or brand-approved demand only).
2. **Load a BidMachine ad** using the Placement API with your Placement ID and `mediation_mode: "first_look"` custom parameter.
3. **If BidMachine loads successfully** — show the BidMachine ad. MAX is never called.
4. **If BidMachine fails to load** — load and show a MAX ad using the normal MAX flow.
For detailed BidMachine SDK integration, refer to [BidMachine Developers Documentation](https://developers.bidmachine.io). For MAX SDK integration, refer to [AppLovin MAX Documentation](https://support.axon.ai/en).
### Setup
You need to add both AppLovin MAX and BidMachine SDK into your project:
```groovy title="build.gradle"
repositories {
google()
mavenCentral()
maven {
url "https://artifactory.bidmachine.io/bidmachine"
}
}
dependencies {
implementation 'com.applovin:applovin-sdk:+'
implementation "io.bidmachine:ads:3.1.1"
}
```
```ruby title="Podfile"
pod 'AppLovinSDK'
pod 'BidMachine', '~> 3.1.0'
```
### Initialization
BidMachine SDK should be properly configured and initialized before AppLovin MAX SDK initialization.
```java title="FirstLookInitialization.java"
// 1. Prepare BidMachine environment - GDPR, CCPA, GPP, Coppa, test mode, etc...
// 2. Initialize BidMachine
BidMachine.initialize(context, "");
// 3. Prepare AppLovin MAX environment - GDPR, CCPA, Coppa, etc...
// https://developers.applovin.com/en/max/android/overview/privacy#consent-other-applicable-flags-and-data-apis
// 4. Initialize AppLovin MAX
// https://developers.applovin.com/en/max/android/overview/new-sdk-initialization-api
AppLovinSdkInitializationConfiguration initConfig = AppLovinSdkInitializationConfiguration.builder("", context)
.setMediationProvider(AppLovinMediationProvider.MAX)
.build();
AppLovinSdk.getInstance(context).initialize(initConfig, appLovinSdkConfiguration -> {
// Start loading ads
});
```
```swift title="FirstLookInitialization.swift"
// 1. Prepare BidMachine environment - GDPR, CCPA, GPP, Coppa, test mode, etc...
/**
BidMachineSdk.shared.populate {
$0.withLoggingMode(true)
}
*/
// 2. Initialize BidMachine
BidMachineSdk.shared.initializeSdk("")
// 3. Prepare AppLovin MAX environment - GDPR, CCPA, Coppa, etc...
/**
https://developers.applovin.com/en/max/ios/overview/privacy#consent-other-applicable-flags-and-data-apis
*/
// 4. Initialize AppLovin MAX
/**
https://developers.applovin.com/en/max/ios/overview/integration/#add-the-sdk-key
*/
ALSdk.shared().initializeSdk { (configuration: ALSdkConfiguration) in
// Start loading ads
}
```
### Interstitial
To implement First Look integration for Interstitial Ad:
1. **Load BidMachine Interstitial** with your Placement ID
```java title="FirstLookInterstitial.java"
AdPlacementConfig config = AdPlacementConfig.interstitialBuilder()
.withPlacementId("YOUR_PLACEMENT_ID")
.withCustomParams(new CustomParams()
.addParam("mediation_mode", "first_look"))
.build();
InterstitialRequest interstitialRequest = new InterstitialRequest.Builder(config).build();
interstitialAd = new InterstitialAd(context)
.setListener(new BidMachineInterstitialListener())
.load(interstitialRequest);
```
```swift title="FirstLookInterstitial.swift"
let placement = try BidMachineSdk.shared.placement(.interstitial) {
$0.withPlacementId("YOUR_PLACEMENT_ID")
$0.withCustomParameters(["mediation_mode": "first_look"])
}
BidMachineSdk.shared.interstitial(placement) { [weak self] interstitial, error in
guard let self = self, let interstitial = interstitial else { return }
interstitial.controller = self.rootViewController
let wrapper = BidMachineDelegateWrapper(parent: self)
interstitial.delegate = wrapper
self.bidMachineDelegateWrapper = wrapper
self.bidMachineInterstitial = interstitial
interstitial.loadAd()
}
```
2. **Handle BidMachine loading callbacks**
```java title="FirstLookInterstitial.java"
@Override
public void onAdLoaded(@NonNull InterstitialAd interstitialAd) {
// BidMachine ad is ready — it will be shown at impression time
bidMachineAdLoaded = true;
}
@Override
public void onAdLoadFailed(@NonNull InterstitialAd interstitialAd, @NonNull BMError bmError) {
// BidMachine failed — load MAX as fallback
loadAppLovinInterstitial();
}
```
```swift title="FirstLookInterstitial.swift"
func didLoadAd(_ ad: any BidMachineAdProtocol) {
// BidMachine ad is ready — it will be shown at impression time
bidMachineAdLoaded = true
}
func didFailLoadAd(_ ad: any BidMachineAdProtocol, _ error: Error) {
// BidMachine failed — load MAX as fallback
loadAppLovinInterstitial()
}
```
3. **Load AppLovin MAX Interstitial** (only called when BidMachine fails)
```java title="FirstLookInterstitial.java"
private void loadAppLovinInterstitial() {
appLovinInterstitialAd = new MaxInterstitialAd("YOUR_AD_UNIT_ID", context);
appLovinInterstitialAd.setListener(new AppLovinInterstitialListener());
appLovinInterstitialAd.loadAd();
}
```
```swift title="FirstLookInterstitial.swift"
private func loadAppLovinInterstitial() {
let interstitial = MAInterstitialAd(adUnitIdentifier: "AD_UNIT_ID")
let wrapper = MaxInterstitialDelegateWrapper(parent: self)
interstitial.delegate = wrapper
self.maxDelegateWrapper = wrapper
interstitial.load()
self.appLovinInterstitial = interstitial
}
```
4. **Show the ad**
```java title="FirstLookInterstitial.java"
private void showInterstitial() {
if (bidMachineAdLoaded && interstitialAd != null && interstitialAd.canShow()) {
// BidMachine filled — show BidMachine ad
interstitialAd.show();
} else if (appLovinInterstitialAd != null && appLovinInterstitialAd.isReady()) {
// MAX filled as fallback — show MAX ad
appLovinInterstitialAd.showAd();
}
}
```
```swift title="FirstLookInterstitial.swift"
private func showInterstitial() {
if bidMachineAdLoaded, let interstitial = bidMachineInterstitial, interstitial.canShow {
// BidMachine filled — show BidMachine ad
interstitial.presentAd()
} else if let appLovinInterstitial = appLovinInterstitial, appLovinInterstitial.isReady {
// MAX filled as fallback — show MAX ad
appLovinInterstitial.show()
}
}
```
Full Interstitial First Look integration sample:
```java title="FirstLookInterstitial.java"
private InterstitialRequest interstitialRequest;
private InterstitialAd interstitialAd;
private MaxInterstitialAd appLovinInterstitialAd;
private boolean bidMachineAdLoaded = false;
private void loadInterstitial() {
// Load BidMachine first with Placement ID
AdPlacementConfig config = AdPlacementConfig.interstitialBuilder()
.withPlacementId("YOUR_PLACEMENT_ID")
.withCustomParams(new CustomParams()
.addParam("mediation_mode", "first_look"))
.build();
interstitialRequest = new InterstitialRequest.Builder(config).build();
interstitialAd = new InterstitialAd(context)
.setListener(new BidMachineInterstitialListener())
.load(interstitialRequest);
}
private void loadAppLovinInterstitial() {
appLovinInterstitialAd = new MaxInterstitialAd("YOUR_AD_UNIT_ID", context);
appLovinInterstitialAd.setListener(new AppLovinInterstitialListener());
appLovinInterstitialAd.loadAd();
}
private void showInterstitial() {
if (bidMachineAdLoaded && interstitialAd != null && interstitialAd.canShow()) {
// BidMachine filled — show BidMachine ad
interstitialAd.show();
} else if (appLovinInterstitialAd != null && appLovinInterstitialAd.isReady()) {
// MAX filled as fallback — show MAX ad
appLovinInterstitialAd.showAd();
}
}
private class BidMachineInterstitialListener implements InterstitialListener {
@Override
public void onAdLoaded(@NonNull InterstitialAd interstitialAd) {
bidMachineAdLoaded = true;
}
@Override
public void onAdLoadFailed(@NonNull InterstitialAd interstitialAd, @NonNull BMError bmError) {
// Load MAX as fallback
loadAppLovinInterstitial();
}
@Override
public void onAdShown(@NonNull InterstitialAd interstitialAd) {
// Handle ad shown
}
@Override
public void onAdShowFailed(@NonNull InterstitialAd interstitialAd, @NonNull BMError bmError) {
// Handle show failure
}
@Override
public void onAdImpression(@NonNull InterstitialAd interstitialAd) {
// Handle impression
}
@Override
public void onAdClicked(@NonNull InterstitialAd interstitialAd) {
// Handle click
}
@Override
public void onAdClosed(@NonNull InterstitialAd interstitialAd, boolean finished) {
// Handle ad closed
}
@Override
public void onAdExpired(@NonNull InterstitialAd interstitialAd) {
// Handle expiration
}
}
private class AppLovinInterstitialListener implements MaxAdListener {
@Override
public void onAdLoaded(@NonNull MaxAd maxAd) {
// MAX ad ready
}
@Override
public void onAdLoadFailed(@NonNull String adUnitId, @NonNull MaxError maxError) {
// MAX ad failed
}
@Override
public void onAdDisplayed(@NonNull MaxAd maxAd) {
// Handle display
}
@Override
public void onAdHidden(@NonNull MaxAd maxAd) {
// Handle hidden
}
@Override
public void onAdClicked(@NonNull MaxAd maxAd) {
// Handle click
}
@Override
public void onAdDisplayFailed(@NonNull MaxAd maxAd, @NonNull MaxError maxError) {
// Handle display failure
}
}
```
```swift title="FirstLookInterstitial.swift"
import BidMachine
import AppLovinSDK
final class InterstitialAd {
weak var rootViewController: UIViewController?
private var bidMachineInterstitial: BidMachineInterstitial?
private var appLovinInterstitial: MAInterstitialAd?
private var bidMachineAdLoaded: Bool = false
// Delegate wrappers
private var bidMachineDelegateWrapper: BidMachineDelegateWrapper?
private var maxDelegateWrapper: MaxInterstitialDelegateWrapper?
func loadAd() {
loadBidMachineInterstitial()
}
private func loadBidMachineInterstitial() {
do {
let placement = try BidMachineSdk.shared.placement(.interstitial) {
$0.withPlacementId("YOUR_PLACEMENT_ID")
$0.withCustomParameters(["mediation_mode": "first_look"])
}
BidMachineSdk.shared.interstitial(placement) { [weak self] interstitial, error in
guard let self = self, let interstitial = interstitial else { return }
interstitial.controller = self.rootViewController
let wrapper = BidMachineDelegateWrapper(parent: self)
interstitial.delegate = wrapper
self.bidMachineDelegateWrapper = wrapper
self.bidMachineInterstitial = interstitial
interstitial.loadAd()
}
} catch {
print("Failed to create placement: \(error)")
}
}
private func loadAppLovinInterstitial() {
let interstitial = MAInterstitialAd(adUnitIdentifier: "AD_UNIT_ID")
let wrapper = MaxInterstitialDelegateWrapper(parent: self)
interstitial.delegate = wrapper
self.maxDelegateWrapper = wrapper
interstitial.load()
self.appLovinInterstitial = interstitial
}
private func showInterstitial() {
if bidMachineAdLoaded, let interstitial = bidMachineInterstitial, interstitial.canShow {
// BidMachine filled — show BidMachine ad
interstitial.presentAd()
} else if let appLovinInterstitial = appLovinInterstitial, appLovinInterstitial.isReady {
// MAX filled as fallback — show MAX ad
appLovinInterstitial.show()
}
}
// MARK: - Forwarded BidMachine callbacks
fileprivate func bidMachineDidLoadAd(_ ad: any BidMachineAdProtocol) {
bidMachineAdLoaded = true
}
fileprivate func bidMachineDidFailLoadAd(_ ad: any BidMachineAdProtocol, _ error: Error) {
// Load MAX as fallback
loadAppLovinInterstitial()
}
fileprivate func bidMachineDidPresentAd(_ ad: any BidMachineAdProtocol) {
// Handle ad shown
}
fileprivate func bidMachineDidFailPresentAd(_ ad: any BidMachineAdProtocol, _ error: Error) {
// Handle show failure
}
fileprivate func bidMachineDidDismissAd(_ ad: any BidMachineAdProtocol) {
// Handle ad closed
}
// MARK: - Forwarded MAX callbacks
fileprivate func maxDidLoad(_ ad: MAAd) {
// MAX ad ready
}
fileprivate func maxDidFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
// MAX ad failed
}
fileprivate func maxDidDisplay(_ ad: MAAd) {
// Handle display
}
fileprivate func maxDidHide(_ ad: MAAd) {
// Handle hidden
}
fileprivate func maxDidClick(_ ad: MAAd) {
// Handle click
}
fileprivate func maxDidFail(toDisplay ad: MAAd, withError error: MAError) {
// Handle display failure
}
}
// MARK: - BidMachine Delegate Wrapper
private final class BidMachineDelegateWrapper: NSObject, BidMachineAdDelegate {
weak var parent: InterstitialAd?
init(parent: InterstitialAd) {
self.parent = parent
super.init()
}
func didLoadAd(_ ad: any BidMachineAdProtocol) {
parent?.bidMachineDidLoadAd(ad)
}
func didFailLoadAd(_ ad: any BidMachineAdProtocol, _ error: any Error) {
parent?.bidMachineDidFailLoadAd(ad, error)
}
func didPresentAd(_ ad: any BidMachineAdProtocol) {
parent?.bidMachineDidPresentAd(ad)
}
func didDismissAd(_ ad: any BidMachineAdProtocol) {
parent?.bidMachineDidDismissAd(ad)
}
func didFailPresentAd(_ ad: any BidMachineAdProtocol, _ error: any Error) {
parent?.bidMachineDidFailPresentAd(ad, error)
}
// Optional extra callbacks
func willPresentScreen(_ ad: any BidMachineAdProtocol) {}
func didDismissScreen(_ ad: any BidMachineAdProtocol) {}
func didUserInteraction(_ ad: any BidMachineAdProtocol) {}
func didExpired(_ ad: any BidMachineAdProtocol) {}
func didTrackImpression(_ ad: any BidMachineAdProtocol) {}
func didTrackInteraction(_ ad: any BidMachineAdProtocol) {}
}
// MARK: - MAX Interstitial Delegate Wrapper
private final class MaxInterstitialDelegateWrapper: NSObject, MAAdDelegate {
weak var parent: InterstitialAd?
init(parent: InterstitialAd) {
self.parent = parent
super.init()
}
func didLoad(_ ad: MAAd) {
parent?.maxDidLoad(ad)
}
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
parent?.maxDidFailToLoadAd(forAdUnitIdentifier: adUnitIdentifier, withError: error)
}
func didDisplay(_ ad: MAAd) {
parent?.maxDidDisplay(ad)
}
func didHide(_ ad: MAAd) {
parent?.maxDidHide(ad)
}
func didClick(_ ad: MAAd) {
parent?.maxDidClick(ad)
}
func didFail(toDisplay ad: MAAd, withError error: MAError) {
parent?.maxDidFail(toDisplay: ad, withError: error)
}
}
```
### Rewarded Ad
To implement First Look integration for Rewarded Ad, follow the same pattern as Interstitial:
1. **Load BidMachine Rewarded** with your Placement ID
```java title="FirstLookRewarded.java"
AdPlacementConfig config = AdPlacementConfig.rewardedBuilder()
.withPlacementId("YOUR_PLACEMENT_ID")
.withCustomParams(new CustomParams()
.addParam("mediation_mode", "first_look"))
.build();
RewardedRequest rewardedRequest = new RewardedRequest.Builder(config).build();
rewardedAd = new RewardedAd(context)
.setListener(new BidMachineRewardedListener())
.load(rewardedRequest);
```
```swift title="FirstLookRewarded.swift"
let placement = try BidMachineSdk.shared.placement(.rewarded) {
$0.withPlacementId("YOUR_PLACEMENT_ID")
$0.withCustomParameters(["mediation_mode": "first_look"])
}
BidMachineSdk.shared.rewarded(placement) { [weak self] rewarded, error in
guard let self = self, let rewarded = rewarded else { return }
rewarded.controller = self.rootViewController
let wrapper = BidMachineDelegateWrapper(parent: self)
rewarded.delegate = wrapper
self.bidMachineDelegateWrapper = wrapper
self.bidMachineRewarded = rewarded
rewarded.loadAd()
}
```
2. **Handle callbacks and load MAX when BidMachine fails** — follow the same logic as Interstitial.
3. **Show the ad** — follow the same logic as Interstitial, ensuring you handle the reward callback appropriately.
Full Rewarded Ad First Look integration sample:
```java title="FirstLookRewarded.java"
private RewardedRequest rewardedRequest;
private RewardedAd rewardedAd;
private MaxRewardedAd appLovinRewardedAd;
private boolean bidMachineAdLoaded = false;
private void loadRewarded() {
AdPlacementConfig config = AdPlacementConfig.rewardedBuilder()
.withPlacementId("YOUR_PLACEMENT_ID")
.withCustomParams(new CustomParams()
.addParam("mediation_mode", "first_look"))
.build();
rewardedRequest = new RewardedRequest.Builder(config).build();
rewardedAd = new RewardedAd(context)
.setListener(new BidMachineRewardedListener())
.load(rewardedRequest);
}
private void loadAppLovinRewarded() {
appLovinRewardedAd = MaxRewardedAd.getInstance("YOUR_AD_UNIT_ID", context);
appLovinRewardedAd.setListener(new AppLovinRewardedListener());
appLovinRewardedAd.loadAd();
}
private void showRewarded() {
if (bidMachineAdLoaded && rewardedAd != null && rewardedAd.canShow()) {
// BidMachine filled — show BidMachine ad
rewardedAd.show();
} else if (appLovinRewardedAd != null && appLovinRewardedAd.isReady()) {
// MAX filled as fallback — show MAX ad
appLovinRewardedAd.showAd();
}
}
private class BidMachineRewardedListener implements RewardedListener {
@Override
public void onAdLoaded(@NonNull RewardedAd rewardedAd) {
bidMachineAdLoaded = true;
}
@Override
public void onAdLoadFailed(@NonNull RewardedAd rewardedAd, @NonNull BMError bmError) {
loadAppLovinRewarded();
}
@Override
public void onAdShowFailed(@NonNull RewardedAd rewardedAd, @NonNull BMError bmError) {
// Handle show failure
}
@Override
public void onAdImpression(@NonNull RewardedAd rewardedAd) {
// Handle impression
}
@Override
public void onAdClicked(@NonNull RewardedAd rewardedAd) {
// Handle click
}
@Override
public void onAdClosed(@NonNull RewardedAd rewardedAd, boolean finished) {
// Handle ad closed
}
@Override
public void onAdRewarded(@NonNull RewardedAd rewardedAd) {
// Grant reward to user
}
@Override
public void onAdExpired(@NonNull RewardedAd rewardedAd) {
// Handle expiration
}
}
private class AppLovinRewardedListener implements MaxRewardedAdListener {
@Override
public void onAdLoaded(@NonNull MaxAd maxAd) {
// MAX ad ready
}
@Override
public void onAdLoadFailed(@NonNull String adUnitId, @NonNull MaxError maxError) {
// MAX ad failed
}
@Override
public void onAdDisplayed(@NonNull MaxAd maxAd) {
// Handle display
}
@Override
public void onAdHidden(@NonNull MaxAd maxAd) {
// Handle hidden
}
@Override
public void onAdClicked(@NonNull MaxAd maxAd) {
// Handle click
}
@Override
public void onAdDisplayFailed(@NonNull MaxAd maxAd, @NonNull MaxError maxError) {
// Handle display failure
}
@Override
public void onRewardedVideoStarted(@NonNull MaxAd maxAd) {
// Handle video start
}
@Override
public void onRewardedVideoCompleted(@NonNull MaxAd maxAd) {
// Handle video completion
}
@Override
public void onUserRewarded(@NonNull MaxAd maxAd, @NonNull MaxReward maxReward) {
// Grant reward to user
}
}
```
```swift title="FirstLookRewarded.swift"
import BidMachine
import AppLovinSDK
final class RewardedAd {
weak var rootViewController: UIViewController?
private var bidMachineRewarded: BidMachineRewarded?
private var appLovinRewarded: MARewardedAd?
private var bidMachineAdLoaded: Bool = false
// Delegate wrappers
private var bidMachineDelegateWrapper: BidMachineDelegateWrapper?
private var maxDelegateWrapper: MaxRewardedDelegateWrapper?
func loadAd() {
loadBidMachineRewarded()
}
private func loadBidMachineRewarded() {
do {
let placement = try BidMachineSdk.shared.placement(.rewarded) {
$0.withPlacementId("YOUR_PLACEMENT_ID")
$0.withCustomParameters(["mediation_mode": "first_look"])
}
BidMachineSdk.shared.rewarded(placement) { [weak self] rewarded, error in
guard let self = self, let rewarded = rewarded else { return }
rewarded.controller = self.rootViewController
let wrapper = BidMachineDelegateWrapper(parent: self)
rewarded.delegate = wrapper
self.bidMachineDelegateWrapper = wrapper
self.bidMachineRewarded = rewarded
rewarded.loadAd()
}
} catch {
print("Failed to create placement: \(error)")
}
}
private func loadAppLovinRewarded() {
let rewarded = MARewardedAd.shared(withAdUnitIdentifier: "AD_UNIT_ID")
let wrapper = MaxRewardedDelegateWrapper(parent: self)
rewarded.delegate = wrapper
self.maxDelegateWrapper = wrapper
rewarded.load()
self.appLovinRewarded = rewarded
}
private func showRewarded() {
if bidMachineAdLoaded, let rewarded = bidMachineRewarded, rewarded.canShow {
// BidMachine filled — show BidMachine ad
rewarded.presentAd()
} else if let appLovinRewarded = appLovinRewarded, appLovinRewarded.isReady {
// MAX filled as fallback — show MAX ad
appLovinRewarded.show()
}
}
// MARK: - Forwarded BidMachine callbacks
fileprivate func bidMachineDidLoadAd(_ ad: any BidMachineAdProtocol) {
bidMachineAdLoaded = true
}
fileprivate func bidMachineDidFailLoadAd(_ ad: any BidMachineAdProtocol, _ error: Error) {
// Load MAX as fallback
loadAppLovinRewarded()
}
fileprivate func bidMachineDidPresentAd(_ ad: any BidMachineAdProtocol) {
// Handle ad shown
}
fileprivate func bidMachineDidFailPresentAd(_ ad: any BidMachineAdProtocol, _ error: Error) {
// Handle show failure
}
fileprivate func bidMachineDidDismissAd(_ ad: any BidMachineAdProtocol) {
// Handle ad closed
}
// MARK: - Forwarded MAX callbacks
fileprivate func maxDidLoad(_ ad: MAAd) {
// MAX ad ready
}
fileprivate func maxDidFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
// MAX ad failed
}
fileprivate func maxDidDisplay(_ ad: MAAd) {
// Handle display
}
fileprivate func maxDidHide(_ ad: MAAd) {
// Handle hidden
}
fileprivate func maxDidClick(_ ad: MAAd) {
// Handle click
}
fileprivate func maxDidFail(toDisplay ad: MAAd, withError error: MAError) {
// Handle display failure
}
fileprivate func maxDidStartRewardedVideo(for ad: MAAd) {
// Handle video start
}
fileprivate func maxDidCompleteRewardedVideo(for ad: MAAd) {
// Handle video completion
}
fileprivate func maxDidRewardUser(for ad: MAAd, with reward: MAReward) {
// Grant reward to user
}
}
// MARK: - BidMachine Delegate Wrapper
private final class BidMachineDelegateWrapper: NSObject, BidMachineAdDelegate {
weak var parent: RewardedAd?
init(parent: RewardedAd) {
self.parent = parent
super.init()
}
func didLoadAd(_ ad: any BidMachineAdProtocol) {
parent?.bidMachineDidLoadAd(ad)
}
func didFailLoadAd(_ ad: any BidMachineAdProtocol, _ error: any Error) {
parent?.bidMachineDidFailLoadAd(ad, error)
}
func didPresentAd(_ ad: any BidMachineAdProtocol) {
parent?.bidMachineDidPresentAd(ad)
}
func didDismissAd(_ ad: any BidMachineAdProtocol) {
parent?.bidMachineDidDismissAd(ad)
}
func didFailPresentAd(_ ad: any BidMachineAdProtocol, _ error: any Error) {
parent?.bidMachineDidFailPresentAd(ad, error)
}
// Optional extra callbacks
func willPresentScreen(_ ad: any BidMachineAdProtocol) {}
func didDismissScreen(_ ad: any BidMachineAdProtocol) {}
func didUserInteraction(_ ad: any BidMachineAdProtocol) {}
func didExpired(_ ad: any BidMachineAdProtocol) {}
func didTrackImpression(_ ad: any BidMachineAdProtocol) {}
func didTrackInteraction(_ ad: any BidMachineAdProtocol) {}
}
// MARK: - MAX Rewarded Delegate Wrapper
private final class MaxRewardedDelegateWrapper: NSObject, MARewardedAdDelegate {
weak var parent: RewardedAd?
init(parent: RewardedAd) {
self.parent = parent
super.init()
}
func didLoad(_ ad: MAAd) {
parent?.maxDidLoad(ad)
}
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
parent?.maxDidFailToLoadAd(forAdUnitIdentifier: adUnitIdentifier, withError: error)
}
func didDisplay(_ ad: MAAd) {
parent?.maxDidDisplay(ad)
}
func didHide(_ ad: MAAd) {
parent?.maxDidHide(ad)
}
func didClick(_ ad: MAAd) {
parent?.maxDidClick(ad)
}
func didFail(toDisplay ad: MAAd, withError error: MAError) {
parent?.maxDidFail(toDisplay: ad, withError: error)
}
func didStartRewardedVideo(for ad: MAAd) {
parent?.maxDidStartRewardedVideo(for: ad)
}
func didCompleteRewardedVideo(for ad: MAAd) {
parent?.maxDidCompleteRewardedVideo(for: ad)
}
func didRewardUser(for ad: MAAd, with reward: MAReward) {
parent?.maxDidRewardUser(for: ad, with: reward)
}
}
```
## Best Practices
1. **Placement Configuration**: Configure your Placement ID in the BidMachine dashboard to define which demand sources participate in the First Look auction (e.g., brand or publisher-approved demand only).
2. **Custom Parameters**: Always add `mediation_mode: "first_look"` to BidMachine requests for proper analytics tracking.
3. **Sequential Loading**: Always load BidMachine first. Only load MAX if BidMachine fails to fill.
4. **Error Handling**: Always implement fallback logic to load MAX when BidMachine fails.
5. **Timeout**: Consider implementing timeout logic to avoid waiting too long for BidMachine responses before falling back to MAX.
---
## Bidding Adapter(3)
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import JavaLabel from '@site/src/components/code-labels/java'
import KotlinLabel from '@site/src/components/code-labels/kotlin'
import SwiftLabel from '@site/src/components/code-labels/swift'
import ObjCLabel from '@site/src/components/code-labels/objc'
BidMachine bidding adapter allows you to use the BidMachine ad platform
within your existing AppLovin MAX mediation.
BidMachine supports banners, MRECs, interstitials and rewarded videos.
[How to Enable BidMachine in AppLovin MAX](/sdk/max/max-console-setup)
## Add the BidMachine Bidding Adapter to Your Build
:::info
IOS deployment target 13.0 or above, XCode 14.3.1 or above.
:::
You can download the SDK through CocoaPods as a dependency.
In your **Podfile** file add the following dependency which includes the BidMachine adapter for use within AppLovin MAX mediation platform:
```ruby title="Podfile"
pod 'AppLovinMediationBidMachineAdapter', '~> 3.2'
```
## Additional Configuration
- [Advanced SDK settings](/sdk/general/ios/advanced/)
- [Data Privacy settings](/sdk/general/ios/privacy/)
---
## Console Setup(Max)
import Image from "@theme/IdealImage";
This page describes how to set up the BidMachine ad platform within your existing AppLovin MAX mediation.
## Bidding Adapter
BidMachine bidding adapter allows you to use the BidMachine ad platform
within your existing AppLovin MAX mediation.
BidMachine supports banners, MRECs, interstitials and rewarded videos.
**Enable BidMachine Bidding in AppLovin MAX Module**
1. **Access ad units**. When you complete your BidMachine setup, log in to your AppLovin account and go to `Ad Units` → `Ad Unit`
2. **Setup Network**. Select BidMachine from the table of Available Networks and click on the
Activate button. Paste all credentials. Then click _Save_.
---
## Overview(Max)
BidMachine Bidding adapter allows you to use the BidMachine ad platform
within your existing AppLovin MAX mediation.
BidMachine supports banners, MRECs, interstitials, rewarded and native ads.
## How to Create a BidMachine Account
1. Create a BidMachine Account at [bidmachine.io](https://bidmachine.io/#sign-up).
2. Upon registration, an activation email containing instructions will be sent to the email address you've provided. Please use the provided instructions to activate your account.
3. To enable BidMachine Ad Inventory through the MAX Mediation platform, you must have an approved monetization account with BidMachine.
## Enable BidMachine in Your MAX Account
1. When you complete your BidMachine setup, log in to your MAX account and select [MAX > Manage > Ad Units](https://dash.applovin.com/o/mediation/ad_units/).
2. Click the MAX ad unit placement on which you want to enable BidMachine.
3. Type the BidMachine **Source ID** values associated with the MAX ad unit you selected.
4. Click the Status bar to activate the network and click ✓ _Save_. This enables BidMachine in the participating networks list for this ad unit.
In order to get Source ID, please refer to this guide - [How to get Source ID under BidMachine Dashboard](/dashboard/source).
## Update Apps-ads.txt
1. Go to BidMachine Dashboard
2. Go to `app-ads.txt` tab
3. Copy the list and append it to your website's apps-ads.txt file
## How to Create an AppLovin MAX Account
In case you don't have a MAX account, please, visit [the official AppLovin Documentation page](https://dash.applovin.com/documentation/mediation/max/get-started-with-max) to proceed.
## Mediation Types
BidMachine supports the following mediation types:
- [**Bidding Adapter**](/sdk/max/max-console-setup) - BidMachine bidding adapter allows you to use the BidMachine ad platform within your existing AppLovin MAX mediation.
---
## AppLovin MAX Publisher Direct Bidding (PDB)
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
## How to add BidMachine to Publisher Direct Bidding (PDB) auction within AppLovin MAX mediation
BidMachine could be easily integrated into the PDB block. Documentation on how to integrate BidMachine SDK can be found [here](/sdk/overview). Step-by-step integration is the following:
- At the start of the application, BidMachine should be initialized according to the following sections: [Android Initialization](/sdk/general/android/overview#initialize-the-sdk) or [iOS Initialization](/sdk/general/ios/overview#initialization).
- The publisher requests an ad from AppLovin and fetches the price of it according to the following documentation: [iOS](https://dash.appLovin.com/documentation/mediation/ios/getting-started/advanced-settings#impression-level-user-revenue-api), [Android](https://dash.appLovin.com/documentation/mediation/android/getting-started/advanced-settings#impression-level-user-revenue-api)
- The publisher requests an ad from BidMachine with the price that was returned by mediation plus `0.01$`, other PDB partners should be requested with the same price. In case there is no winner or no bid on the mediation side, the publisher shall request BidMachine with a Price Floor equal to `$0.01`
- If BidMachine wins the PDB auction - the publisher loads it's creative and uses it for impressions later
- If there are multiple demand sources in the PDB auction, the publisher should notify BidMachine with win and loss notification. Publisher shall populate the auction winning price via a loss notice URL according to this documentation: [iOS](https://docs.bidMachine.io/docs/in-house-mediation-1#mediation), [Android](https://docs.bidMachine.io/docs/in-house-mediation#winloss-notifications).
- The publisher should set up an interval for the BidMachine request in PDB auction not less than:
- **10 seconds** for Banner/MREC
- **15 seconds** for Interstitial
- **30 seconds** for Rewarded Video
### Integration
You need to add both AppLovin MAX and BidMachine SDK into your project:
```groovy title="build.gradle"
repositories {
google()
mavenCentral()
maven {
url "https://artifactory.bidmachine.io/bidmachine"
}
}
dependencies {
implementation 'com.applovin:applovin-sdk:+'
implementation "io.bidmachine:ads:3.1.1"
}
```
```ruby title="Podfile"
pod 'AppLovinSDK'
pod 'BidMachine', '~> 3.1.0'
```
### Initialization
Change your AppLovin MAX SDK initialization logic. BidMachine SDK should be properly configured and initialized before AppLovin MAX SDK will be initialized.
```java title="MyClass.java"
// 1. Prepare BidMachine environment - GDPR, CCPA, GPP, Coppa, test mode, etc...
// 2. Initializing BidMachine
BidMachine.initialize(context, "");
// 3. Prepare AppLovin MAX environment - GDPR, CCPA, Coppa, etc...
// https://developers.applovin.com/en/max/android/overview/privacy#consent-other-applicable-flags-and-data-apis
// 4. Initialize AppLovin MAX
// https://developers.applovin.com/en/max/android/overview/new-sdk-initialization-api
AppLovinSdkInitializationConfiguration initConfig = AppLovinSdkInitializationConfiguration.builder("«SDK-key»", context)
.setMediationProvider(AppLovinMediationProvider.MAX)
.build();
AppLovinSdk.getInstance(context).initialize(initConfig, appLovinSdkConfiguration -> {
// Start loading ads
});
```
```swift title="MyClass.swift"
// 1. Prepare BidMachine environment - GDPR, CCPA, GPP, Coppa, test mode, etc...
/**
BidMachineSdk.shared.populate {
$0.withLoggingMode(true)
}
*/
// 2. Initializing BidMachine
BidMachineSdk.shared.initializeSdk("")
// 3. Prepare AppLovin MAX environment - GDPR, CCPA, Coppa, etc...
/**
https://developers.appLovin.com/en/max/ios/overview/privacy#consent-other-applicable-flags-and-data-apis
*/
// 4. Initialize AppLovin MAX
/**
/https://developers.appLovin.com/en/max/ios/overview/integration/#add-the-sdk-key
*/
ALSdk.shared().initializeSdk { (configuration: ALSdkConfiguration) in
// Start loading ads
}
```
:::warning
The placement capping feature is not available for the PDB auction
:::
### Interstitial
To implement PDB auction over Interstitial Ad you need to follow the next steps:
1. **Load AppLovin MAX Interstitial**
```java Android title="MyClass.java"
appLovinInterstitialAd = new MaxInterstitialAd("YOUR_AD_UNIT_ID", context);
appLovinInterstitialAd.setListener(new AppLovinInterstitialListener());
appLovinInterstitialAd.loadAd();
```
```swift title="MyClass.swift"
let interstitial = MAInterstitialAd(adUnitIdentifier: "AD_UNIT_ID")
interstitial.delegate = self
interstitial.load()
self.appLovinInterstitial = interstitial
```
2. **Handle loading callback methods from `MaxAdListener` (Android) and `MAAdDelegate` (iOS)**
```java title="MyClass.java"
@Override
public void onAdLoaded(@NonNull MaxAd maxAd) {
loadBidMachineInterstitial(maxAd);
}
@Override
public void onAdLoadFailed(@NonNull String adUnitId, @NonNull MaxError maxError) {
loadBidMachineInterstitial(null);
}
```
```swift title="MyClass.swift"
func didLoad(_ ad: MAAd) {
loadBidMachineInterstitial(ad)
}
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
loadBidMachineInterstitial(nil)
}
```
3. **Load BidMachine Interstitial**. If AppLovin MAX Interstitial has been loaded,
you will need to add `price floor` to the BidMachine request.
Otherwise don't pass anything, BidMachine will use the default value of **0.01$**.
`price floor` is a `revenue` value from `MAAd` object transformed to `CPM` (multiplied by **1000**) by adding `0.01$`. `priceFloor = ad.revenue * 1000 + 0.01`
```java title="MyClass.java"
// Get revenue from AppLovin MAX and convert it to CPM
appLovinPrice = maxAd.getRevenue() * 1000;
// Calculate price floor
double priceFloor = appLovinPrice + 0.01;
// Make parameters object
PriceFloorParams priceFloorParams = new PriceFloorParams()
.addPriceFloor(priceFloor);
// Set object to the request
requestBuilder.setPriceFloorParams(priceFloorParams);
```
```swift title="MyClass.swift"
// Calculate price floor
let priceFloor = ad.revenue * 1000 + 0.01
// Create request configuration
let configuration = try BidMachineSdk.shared.requestConfiguration(.interstitial)
// Set price floor to the request configuration
// Name parameter is optional and can be any string
configuration.populate {
$0.appendPriceFloor(priceFloor, "Placement-\(configuration.placement.name)")
}
```
4. **Add `mediation_mode` as `pdb_max` to request custom parameters**.
It will allow the split data in the dashboard
```java title="MyClass.java"
CustomParams customParams = new CustomParams()
.addParam("mediation_mode", "pdb_max");
requestBuilder.setCustomParams(customParams);
```
```swift title="MyClass.swift"
configuration.populate {
$0.withCustomParameters(["mediation_mode": "pdb_max"])
}
```
5. **Load BidMachine Interstitial**.
```java title="MyClass.java"
interstitialAd = new InterstitialAd(context)
.setListener(new BidMachineInterstitialListener())
.load(requestBuilder.build());
```
```swift title="MyClass.swift"
BidMachineSdk.shared.interstitial(configuration) { interstitial, error in
guard let interstitial = interstitial else { return }
interstitial.loadAd()
self.bidMachineInterstitial = interstitial
}
```
6. **Show ad**. At the impression opportunity moment, you need to check if the BidMachine ad is ready or not.
```java title="MyClass.java"
if (interstitialAd != null
&& interstitialAd.canShow()
&& interstitialAd.getAuctionResult() != null
&& interstitialAd.getAuctionResult().getPrice() >= appLovinPrice) {
interstitialAd.show();
} else if (appLovinInterstitialAd != null) {
appLovinInterstitialAd.showAd(activity);
}
```
```swift title="MyClass.swift"
if let interstitial = bidMachineInterstitial, interstitial.canShow, interstitial.auctionInfo.price >= appLovinPrice {
interstitial.presentAd()
} else {
self.appLovinInterstitial?.show()
}
```
7. _Optional_. For the PDB auction, you might want to implement loading timeout logic. We recommend adding at least **15 seconds** loading timeout.
Full Interstitial PDB auction integration sample:
```java title="MyClass.java"
private void loadInterstitial() {
appLovinInterstitialAd = new MaxInterstitialAd("YOUR_AD_UNIT_ID", context);
appLovinInterstitialAd.setListener(new AppLovinInterstitialListener());
appLovinInterstitialAd.loadAd();
}
private void loadBidMachineInterstitial(@Nullable MaxAd maxAd) {
if (interstitialAd != null) {
interstitialAd.destroy();
}
InterstitialRequest.Builder requestBuilder = new InterstitialRequest.Builder();
if (maxAd != null) {
// Get revenue from AppLovin MAX and convert it to CPM
appLovinPrice = maxAd.getRevenue() * 1000;
// Calculate price floor
double priceFloor = appLovinPrice + 0.01;
// Make parameters object
PriceFloorParams priceFloorParams = new PriceFloorParams()
.addPriceFloor(priceFloor);
// Set object to the request
requestBuilder.setPriceFloorParams(priceFloorParams);
}
CustomParams customParams = new CustomParams()
.addParam("mediation_mode", "pdb_max");
requestBuilder.setCustomParams(customParams);
interstitialAd = new InterstitialAd(this)
.setListener(new BidMachineInterstitialListener())
.load(requestBuilder.build());
}
private void onLoadInterstitialCompleted() {
// Handling the end of loading
}
private void showInterstitial() {
if (interstitialAd != null
&& interstitialAd.canShow()
&& interstitialAd.getAuctionResult() != null
&& interstitialAd.getAuctionResult().getPrice() >= appLovinPrice) {
interstitialAd.show();
} else if (appLovinInterstitialAd != null) {
appLovinInterstitialAd.showAd(activity);
}
}
private class AppLovinInterstitialListener implements MaxAdListener {
@Override
public void onAdLoaded(@NonNull MaxAd maxAd) {
loadBidMachineInterstitial(maxAd);
}
@Override
public void onAdLoadFailed(@NonNull String adUnitId, @NonNull MaxError maxError) {
loadBidMachineInterstitial(null);
}
// Other callbacks
}
private class BidMachineInterstitialListener implements InterstitialListener {
@Override
public void onAdLoaded(@NonNull InterstitialAd interstitialAd) {
onLoadInterstitialCompleted();
}
@Override
public void onAdLoadFailed(@NonNull InterstitialAd interstitialAd, @NonNull BMError bmError) {
onLoadInterstitialCompleted();
}
// Other callbacks
}
```
```swift title="MyClass.swift"
import BidMachine
import AppLovinSDK
final class ViewController: UIViewController {
private var bidMachineInterstitial: BidMachineInterstitial?
private var appLovinInterstitial: MAInterstitialAd?
private var appLovinPrice: Double = 0
override func viewDidLoad() {
super.viewDidLoad()
loadAppLovinInterstitial()
}
private func loadAppLovinInterstitial() {
let interstitial = MAInterstitialAd(adUnitIdentifier: "AD_UNIT_ID")
interstitial.delegate = self
interstitial.load()
self.appLovinInterstitial = interstitial
}
private func loadBidMachineInterstitial(_ ad: MAAd?) throws {
let configuration = try BidMachineSdk.shared.requestConfiguration(.interstitial)
if let ad = ad {
let priceFloor = ad.revenue * 1000 + 0.01
configuration.populate {
$0.appendPriceFloor(priceFloor, "Placement-\(configuration.placement.name)")
}
}
configuration.populate {
$0.withCustomParameters(["mediation_mode": "pdb_max"])
}
BidMachineSdk.shared.interstitial(configuration) { [weak self] interstitial, error in
guard
let self = self,
let interstitial = interstitial
else { return }
interstitial.controller = self
interstitial.delegate = self
self.bidMachineInterstitial = interstitial
interstitial.loadAd()
}
}
private func showInterstitial() {
if let interstitial = bidMachineInterstitial, interstitial.canShow, interstitial.auctionInfo.price >= appLovinPrice {
interstitial.presentAd()
} else {
self.appLovinInterstitial?.show()
}
}
}
extension ViewController: MAAdDelegate {
func didLoad(_ ad: MAAd) {
try? loadBidMachineInterstitial(ad)
}
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
try? loadBidMachineInterstitial(nil)
}
func didDisplay(_ ad: MAAd) {
}
func didHide(_ ad: MAAd) {
}
func didClick(_ ad: MAAd) {
}
func didFail(toDisplay ad: MAAd, withError error: MAError) {
}
}
extension ViewController: BidMachineAdDelegate {
func didLoadAd(_ ad: any BidMachine.BidMachineAdProtocol) {}
func didFailLoadAd(_ ad: any BidMachine.BidMachineAdProtocol, _ error: any Error) {}
}
```
### Rewarded Ad
To implement PDB auction over Rewarded Ad you need to follow the next steps:
1. **Load AppLovin MAX Rewarded**
```java title="MyClass.java"
appLovinRewardedAd = MaxRewardedAd.getInstance("YOUR_AD_UNIT_ID", context);
appLovinRewardedAd.setListener(new AppLovinRewardedListener());
appLovinRewardedAd.loadAd();
```
```swift title="MyClass.swift"
let rewarded = MARewardedAd.shared(withAdUnitIdentifier: "AD_UNIT_ID")
rewarded.delegate = self
rewarded.load()
self.appLovinRewarded = rewarded
```
2. **Handle loading callback methods from `MaxRewardedAdListener` (Android) and `MARewardedAdDelegate` (iOS)**
```java title="MyClass.java"
@Override
public void onAdLoaded(@NonNull MaxAd maxAd) {
loadBidMachineRewarded(maxAd);
}
@Override
public void onAdLoadFailed(@NonNull String adUnitId, @NonNull MaxError maxError) {
loadBidMachineRewarded(null);
}
```
```swift title="MyClass.swift"
func didLoad(_ ad: MAAd) {
loadBidMachineRewarded(ad)
}
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
loadBidMachineRewarded(nil)
}
```
3. **Load BidMachine Rewarded**. If AppLovin MAX Rewarded has been loaded,
you will need to add `price floor` to the BidMachine request.
Otherwise don't pass anything, BidMachine will use the default value of **0.01$**.
`price floor` is a `revenue` value from `MAAd` object
transformed to `CPM` (multiplied by **1000**) by adding `0.01$`. `priceFloor = ad.revenue * 1000 + 0.01`
```java title="MyClass.java"
// Get revenue from AppLovin MAX and convert it to CPM
appLovinPrice = maxAd.getRevenue() * 1000;
// Calculate price floor
double priceFloor = appLovinPrice + 0.01;
// Make parameters object
PriceFloorParams priceFloorParams = new PriceFloorParams()
.addPriceFloor(priceFloor);
// Set object to the request
requestBuilder.setPriceFloorParams(priceFloorParams);
```
```swift title="MyClass.swift"
// Calculate price floor
let priceFloor = ad.revenue * 1000 + 0.01
// Create request configuration
let configuration = try BidMachineSdk.shared.requestConfiguration(.rewarded)
// Set price floor to the request configuration
// Name parameter is optional and can be any string
configuration.populate {
$0.appendPriceFloor(priceFloor, "Placement-\(configuration.placement.name)")
}
```
4. **Add `mediation_mode` as `pdb_max` to request custom parameters**. It will allow to split data in dashboard
```java title="MyClass.java"
CustomParams customParams = new CustomParams().addParam("mediation_mode", "pdb_max");
requestBuilder.setCustomParams(customParams);
```
```swift title="MyClass.swift"
configuration.populate {
$0.withCustomParameters(["mediation_mode": "pdb_max"])
}
```
5. **Load BidMachine Rewarded**.
```java title="MyClass.java"
rewardedAd = new RewardedAd(context)
.setListener(new BidMachineRewardedListener())
.load(requestBuilder.build());
```
```swift title="MyClass.swift"
BidMachineSdk.shared.rewarded(configuration) { rewarded, error in
guard let rewarded = rewarded else { return }
rewarded.loadAd()
self.bidMachineRewarded = rewarded
}
```
6. **Show ad**. At the impression opportunity moment, you need to check if the BidMachine ad is ready or not.
```java title="MyClass.java"
if (rewardedAd != null
&& rewardedAd.canShow()
&& rewardedAd.getAuctionResult() != null
&& rewardedAd.getAuctionResult().getPrice() >= appLovinPrice) {
rewardedAd.show();
} else if (appLovinRewardedAd != null && appLovinRewardedAd.isReady()) {
appLovinRewardedAd.showAd(activity);
}
```
```swift title="MyClass.swift"
if let rewarded = bidMachineRewarded, rewarded.canShow, rewarded.auctionInfo.price >= appLovinPrice {
rewarded.presentAd()
} else {
self.appLovinRewarded?.show()
}
```
7. **Optional**. For the PDB auction, you might want to implement loading timeout logic. We recommend adding at least **30 seconds** loading timeout.
Full Rewarded Ad PDB auction integration sample:
```java title="MyClass.java"
private void loadRewarded() {
appLovinRewardedAd = MaxRewardedAd.getInstance("", context);
appLovinRewardedAd.setListener(new AppLovinRewardedListener());
appLovinRewardedAd.loadAd();
}
private void loadBidMachineRewarded(@Nullable MaxAd maxAd) {
if (rewardedAd != null) {
rewardedAd.destroy();
}
RewardedRequest.Builder requestBuilder = new RewardedRequest.Builder();
if (maxAd != null) {
// Get revenue from AppLovin MAX and convert it to CPM
appLovinPrice = maxAd.getRevenue() * 1000;
// Calculate price floor
double priceFloor = appLovinPrice + 0.01;
// Make parameters object
PriceFloorParams priceFloorParams = new PriceFloorParams()
.addPriceFloor(priceFloor);
// Set object to the request
requestBuilder.setPriceFloorParams(priceFloorParams);
}
CustomParams customParams = new CustomParams()
.addParam("mediation_mode", "pdb_max");
requestBuilder.setCustomParams(customParams);
rewardedAd = new RewardedAd(context)
.setListener(new BidMachineRewardedListener())
.load(requestBuilder.build());
}
private void onLoadRewardedCompleted() {
// Handling the end of loading
}
private void showRewarded() {
if (rewardedAd != null
&& rewardedAd.canShow()
&& rewardedAd.getAuctionResult() != null
&& rewardedAd.getAuctionResult().getPrice() >= appLovinPrice) {
rewardedAd.show();
} else if (appLovinRewardedAd != null && appLovinRewardedAd.isReady()) {
appLovinRewardedAd.showAd(activity);
}
}
private class AppLovinRewardedListener implements MaxRewardedAdListener {
@Override
public void onAdLoaded(@NonNull MaxAd maxAd) {
loadBidMachineRewarded(maxAd);
}
@Override
public void onAdLoadFailed(@NonNull String adUnitId, @NonNull MaxError maxError) {
loadBidMachineRewarded(null);
}
// Other callbacks
}
private class BidMachineRewardedListener implements RewardedListener {
@Override
public void onAdLoaded(@NonNull RewardedAd rewardedAd) {
onLoadRewardedCompleted();
}
@Override
public void onAdLoadFailed(@NonNull RewardedAd rewardedAd, @NonNull BMError bmError) {
onLoadRewardedCompleted();
}
// Other callbacks
}
```
```swift title="MyClass.swift"
import BidMachine
import AppLovinSDK
final class ViewController: UIViewController {
private var bidMachineRewarded: BidMachineRewarded?
private var appLovinRewarded: MARewardedAd?
private var appLovinPrice: Double = 0
override func viewDidLoad() {
super.viewDidLoad()
loadAppLovinRewarded()
}
private func loadAppLovinRewarded() {
let rewarded = MARewardedAd.shared(withAdUnitIdentifier: "AD_UNIT_ID")
rewarded.delegate = self
rewarded.load()
self.appLovinRewarded = rewarded
}
private func loadBidMachineRewarded(_ ad: MAAd?) throws {
let configuration = try BidMachineSdk.shared.requestConfiguration(.rewarded)
if let ad = ad {
let priceFloor = ad.revenue * 1000 + 0.01
configuration.populate {
$0.appendPriceFloor(priceFloor, "Placement-\(configuration.placement.name)")
}
}
configuration.populate {
$0.withCustomParameters(["mediation_mode": "pdb_max"])
}
BidMachineSdk.shared.rewarded(configuration) { [weak self] rewarded, error in
guard
let self = self,
let rewarded = rewarded
else { return }
rewarded.controller = self
rewarded.delegate = self
self.bidMachineRewarded = rewarded
rewarded.loadAd()
}
}
private func showRewarded() {
if let rewarded = bidMachineRewarded, rewarded.canShow, rewarded.auctionInfo.price >= appLovinPrice {
rewarded.presentAd()
} else {
self.appLovinRewarded?.show()
}
}
}
extension ViewController: MARewardedAdDelegate {
func didLoad(_ ad: MAAd) {
try? loadBidMachineRewarded(ad)
}
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
try? loadBidMachineRewarded(nil)
}
func didDisplay(_ ad: MAAd) {
}
func didHide(_ ad: MAAd) {
}
func didClick(_ ad: MAAd) {
}
func didFail(toDisplay ad: MAAd, withError error: MAError) {
}
func didRewardUser(for ad: MAAd, with reward: MAReward) {
}
}
extension ViewController: BidMachineAdDelegate {
func didLoadAd(_ ad: any BidMachine.BidMachineAdProtocol) {}
func didFailLoadAd(_ ad: any BidMachine.BidMachineAdProtocol, _ error: any Error) {}
}
```
---
## Waterfall Custom Adapter(Max)
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
## Add Custom SDK Network Settings
In the MAX Dashboard, select [MAX > Mediation > Manage > Networks](https://dash.applovin.com/o/mediation/networks/).
Then click **Click here to add a Custom Network** at the bottom of the page. **Create Custom Network** page will appear. Add the information about your custom network:
- **Network Type** - Choose SDK.
- **Name** - Type in the name BMWaterfall.
- **iOS Adapter Class Name** - Type in the class name of your custom network adapter class (for example, **BDMMAXAdapter**).
- **Android Adapter Class Name** - Type in the fully-qualified class name of your custom network adapter class (for example, **com.applovin.mediation.adapters.BDMMAXAdapter**).
## Enable the Custom SDK Network
Open [MAX > Mediation > Manage > Ad Units](https://dash.applovin.com/o/mediation/ad_units/) in the MAX dashboard and select an ad unit where you want to add the custom SDK network that you created in the previous step (**BMWaterfall**). Enable it and enter the information for each placement:
- **Status** - Enabled
- **App ID** - Your BidMachine source id
- **Placement ID** - Any string (e.g. `bm_5`)
- **Custom params** - `{"price": 5}` - bid floor of the line item
- **eCPM** - The same as bid floor
- Find out number of line items and their prices with your account manager
- Repeat for All ad units where you want to use Custom Adaptor
## Integrate custom adapter in your build
You should use _BidMachine Waterfall Custom Adapter_ with _AppLovin BidMachine Bidding Adapter_ to maximize your performance and the revenue.
:::note
You should use the same SDK version of custom adapter and the AppLovin BidMachine adapter.
:::
### Android
Add the following to your app-level `build.gradle` file:
```groovy title="build.gradle"
implementation "com.applovin.mediation:bidmachine-adapter:2.4.0.0"
implementation "com.applovin.mediation:bidmachine-waterfall-adapter:2.4.0.0"
```
and BidMachine's Maven repository in the repositories:
```groovy title="build.gradle"
repositories {
google()
mavenCentral()
maven {
url 'https://artifactory.bidmachine.io/bidmachine'
}
}
```
### iOS
In the Podfile add the following line to add BidMachine custom adapter for AppLovin MAX:
```ruby
source 'https://github.com/appodeal/CocoaPods.git'
pod 'AppLovinMediationBidMachineAdapter', '2.4.0.0.0'
pod 'BidMachine-AppLovin-Waterfall-Adapter', '~> 2.4.0.0'
```
### Unity
In the `Assets/MaxSdk/Mediation/BidMachine/Editor/` in the **Dependencies** file add following lines:
```xml xml
https://artifactory.bidmachine.io/bidmachinehttps://github.com/appodeal/CocoaPods.git
```
---
## Getting Started(Sdk)
import Step from '@site/src/components/mdx/step'
import Stepper from '@site/src/components/mdx/stepper'
## What is BidMachine
BidMachine is an SDK (Software Development Kit) and a platform designed for mobile app
developers and publishers in the field of mobile advertising.
It provides tools and resources to help developers and publishers effectively
manage and optimize their ad monetization strategies within their mobile applications.
## How to enable BidMachine
Create a BidMachine Account at [bidmachine.io](https://bidmachine.io/#sign-up).
Upon registration, an activation email containing instructions will be sent
to the email address you've provided. Please use the provided instructions
to activate your account.
After activating your account, you can log in to the [BidMachine dashboard](https://dashboard.bidmachine.io/).
Here, you can configure your account settings, including payment information,
ad formats, and other preferences to tailor the platform to your needs.
Update your `app-ads.txt` file with the BidMachine data fron the dashboard.
You can find the file in [the dashboard](https://dashboard.bidmachine.io/app-ads/file) under `Dashboard > app-ads.txt`.
Update your CMP (Consent Management Platform) to include [recommended vendors](/sdk/general/tcf-vendors), allowing them to collect and process user consent.
Integrate the BidMachine SDK into your mobile application.
You can find supported intgration types on [the following page](/sdk/integration-types).
---
## Publisher Direct Bidding documentation
## General Publisher Direct Bidding logic description
Publisher Direct Bidding (PDB) is a type of integration
that allows publishers to boost revenue by adding an
extra layer of an auction after the usual meditation has finished its work.
This auction is fully controlled by the publisher and is called PostBid.
Whenever mediation provides an ad with a price - the publisher
is asking PDB partners if they are willing to pay more for an impression opportunity.
Flow is the following:
- The publisher requests an ad from mediation (in this case - IronSource)
- Mediations provide an advertisement with some price
- The publisher is creating a PDB auction across all PDB partners
- All partners should be requested simultaneously within PDB auction
- The publisher chooses the winner of the auction and the winner's ad should be shown as is's the most expensive
- If no PDB partners were able to provide an ad - the publisher should show the ad that was given by mediation
A step-by-step guide for specific mediation can be found here:
- [IronSource](/sdk/ironsource/pdb)
- [AppLovin MAX](/sdk/max/pdb)
- [In-House Mediation](/sdk/general/pdb)
---
## Overview(Ssp)
BidMachine bidding supports the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) protocol to receive bid requests from supply partners and return bid responses. To integrate with BidMachine, partners must use the BidMachine SDK and ensure their bid requests comply with the OpenRTB 2.5 specification.
## Protocol
- Transport: `HTTP`
- Security: TLS 1.2 or higher is recommended
## Request Regions
BidMachine servers are hosted in three regions to minimize latency:
- **US**
- **EU**
- **APAC**
We recommend using the region endpoint closest to your infrastructure.
## Endpoint
After agreement on this specification, BidMachine will provide a custom endpoint for your RTB calls.
## Supported Ad Formats
BidMachine participates exclusively in mobile in-app auctions. Supported ad formats:
- **Fullscreen Banner**: 320×480, 480×320, 768×1024, 1024×768
- **Small Banner**: 320×50, 728×90
- **Skippable Video**: 320×480, 480×320, 768×1024, 1024×768
- **Rewarded Video**: 320×480, 480×320, 768×1024, 1024×768
- **Native Ads**
## Supported Currency
- `USD` only
## Supported Auction Type
- **First-price auction** only
## Bid Request Requirements
Each bid request must contain exactly one `imp` object. Key OpenRTB fields:
- `app.bundle` (required)
- `app.storeurl` (required)
- `app.name` (required)
- `imp.instl` (required)
- `device.os` (required)
- `tmax` (required; recommended `>1000` ms)
For a complete Bid Request specification, see the [BidMachine OpenRTB Bid Request Spec](/sdk/ssp/request/specification).
:::note
- Partners should share a sample bid request they plan to use for integration.
- If you have a custom bid request spec, please contact your BidMachine Account Manager.
:::
## Bid Response
BidMachine’s bid response follows the OpenRTB 2.5 protocol.
#### No-Bid Response
To indicate no-bid, return an empty response body with HTTP status code `204`.
#### Win/Loss Notifications
- Provide both **win** (`nurl`) and **loss** (`lurl`) notification URLs in your bid response.
- Use the appropriate loss codes as defined by OpenRTB.
- If you require custom auction macros in your notification URLs, notify your BidMachine Account Manager.
For sample request and response payloads, see the [Response](/sdk/ssp/response/examples) and [Request](/sdk/ssp/request/examples) Examples.
---
## Enumerated Lists Specification(Request)
## Ad Position
| Value | Description |
| ----- | --------------------------------------------------------------------------------------- |
| `0` | Unknown |
| `1` | Above the Fold |
| `2` | *Deprecated* May or may not be initially visible depending on screen size/resolution. |
| `3` | Below the Fold |
| `4` | Header |
| `5` | Footer |
| `6` | Sidebar |
| `7` | Full Screen |
## API Frameworks
| Value | Description |
| ----- | ------------ |
| `1` | VPAID 1.0 |
| `2` | VPAID 2.0 |
| `3` | MRAID-1 |
| `4` | ORMMA |
| `5` | MRAID-2 |
## Banner Ad Types
| Value | Description |
| ----- | -------------------------------------------------- |
| `1` | XHTML Text Ad (usually mobile) |
| `2` | XHTML Banner Ad (usually mobile) |
| `3` | JavaScript Ad; must be valid XHTML (script tags) |
| `4` | `iframe` |
## Connection Type
| Value | Description |
| ----- | ------------------------------------- |
| `0` | Unknown |
| `1` | Ethernet |
| `2` | Wi‑Fi |
| `3` | Cellular Network – Unknown Generation |
| `4` | Cellular Network – 2G |
| `5` | Cellular Network – 3G |
| `6` | Cellular Network – 4G |
## Content Categories
:::warning
List is truncated; see full IAB taxonomy as needed.
:::
| Value | Description |
| -------- | ---------------------------- |
| `IAB1` | Arts & Entertainment |
| `IAB1-1` | Books & Literature |
| `IAB1-2` | Celebrity Fan/Gossip |
| `IAB1-3` | Fine Art |
| `IAB1-4` | Humor |
| `IAB1-5` | Movies |
| `IAB1-6` | Music |
| `IAB1-7` | Television |
| `IAB2` | Automotive |
| `IAB2-1` | Auto Parts |
| `IAB2-2` | Auto Repair |
| `IAB2-3` | Buying/Selling Cars |
| `IAB2-4` | Car Culture |
| ... | ... |
## Content Delivery Methods
| Value | Description |
| ----- | ------------- |
| `1` | Streaming |
| `2` | Progressive |
## Creative Attributes
| Value | Description |
| ----- | ---------------------------------------------------------- |
| `1` | Audio Ad (Auto-Play) |
| `2` | Audio Ad (User Initiated) |
| `3` | Expandable (Automatic) |
| `4` | Expandable (User Initiated—Click) |
| `5` | Expandable (User Initiated—Rollover) |
| `6` | In-Banner Video Ad (Auto-Play) |
| `7` | In-Banner Video Ad (User Initiated) |
| `8` | Pop (Over, Under, or Upon Exit) |
| `9` | Provocative or Suggestive Imagery |
| `10` | Shaky/Flashing/Flickering/Extreme Animation/Smileys |
| `11` | Surveys |
| `12` | Text Only |
| `13` | User Interactive (e.g., Embedded Games) |
| `14` | Windows Dialog or Alert Style |
| `15` | Has Audio On/Off Button |
| `16` | Ad Can Be Skipped (e.g., Skip Button on Pre-Roll Video) |
## Device Type
| Value | Description |
| ----- | ------------------- |
| `1` | Mobile/Tablet |
| `2` | Personal Computer |
| `3` | Connected TV |
| `4` | Phone |
| `5` | Tablet |
| `6` | Connected Device |
| `7` | Set Top Box |
## Expandable Direction
| Value | Description |
| ----- | ------------- |
| `1` | Left |
| `2` | Right |
| `3` | Up |
| `4` | Down |
| `5` | Full Screen |
## Location Type
| Value | Description |
| ----- | ------------------------------------ |
| `1` | GPS/Location Services |
| `2` | IP Address |
| `3` | User Provided (e.g., registration) |
## No-Bid Reason Codes
| Value | Description |
| ----- | ------------------------------ |
| `0` | Unknown Error |
| `1` | Technical Error |
| `2` | Invalid Request |
| `3` | Known Web Spider |
| `4` | Suspected Non-Human Traffic |
| `5` | Cloud/Data Center/Proxy IP |
| `6` | Unsupported Device |
| `7` | Blocked Publisher or Site |
| `8` | Unmatched User |
## Loss Reason Codes
| Value | Description |
| ----- | ------------------------------------------------------------------------------------------ |
| `0` | Bid Won |
| `1` | Internal Error |
| `2` | Impression Opportunity Expired |
| `3` | Invalid Bid Response |
| `4` | Invalid Deal ID |
| `5` | Invalid Auction ID |
| `6` | Invalid (malformed) Advertiser Domain |
| `7` | Missing Markup |
| `8` | Missing Creative ID |
| `9` | Missing Bid Price |
| `10` | Missing Minimum Creative Approval Data |
| `100` | Bid was Below Auction Floor |
| `101` | Bid was Below Deal Floor |
| `102` | Lost to Higher Bid |
| `103` | Lost to a Bid for a PMP Deal |
| `104` | Buyer Seat Blocked |
| `200` | Creative Filtered—General; reason unknown. |
| `201` | Creative Filtered—Pending processing by Exchange (e.g., approval, transcoding) |
| `202` | Creative Filtered—Disapproved by Exchange |
| `203` | Creative Filtered—Size Not Allowed |
| `204` | Creative Filtered—Incorrect Creative Format |
| `205` | Creative Filtered—Advertiser Exclusions |
| `206` | Creative Filtered—App Bundle Exclusions |
| `207` | Creative Filtered—Not Secure |
| `208` | Creative Filtered—Language Exclusions |
| `209` | Creative Filtered—Category Exclusions |
| `210` | Creative Filtered—Creative Attribute Exclusions |
| `211` | Creative Filtered—Ad Type Exclusions |
| `212` | Creative Filtered—Animation Too Long |
| `213` | Creative Filtered—Not Allowed in PMP Deal |
## VAST Companion Types
| Value | Description |
| ----- | -------------------|
| `1` | Static Resource |
| `2` | HTML Resource |
| `3` | `iframe` Resource |
## Video Bid Response Protocols
| Value | Description |
| ------ | --------------------- |
| `1` | VAST 1.0 |
| `2` | VAST 2.0 |
| `3` | VAST 3.0 |
| `4` | VAST 1.0 Wrapper |
| `5` | VAST 2.0 Wrapper |
| `6` | VAST 3.0 Wrapper |
## Video Linearity
| Value | Description |
| ----- | ------------------ |
| `1` | Linear / In-Stream |
| `2` | Non-Linear / Overlay|
## Video Playback Methods
| Value | Description |
| ----- | --------------------- |
| `1` | Auto-Play Sound On |
| `2` | Auto-Play Sound Off |
| `3` | Click-to-Play |
| `4` | Mouse-Over |
## Video Quality
| Value | Description |
| ----- | ----------------------------- |
| `0` | Unknown |
| `1` | Professionally Produced |
| `2` | Prosumer |
| `3` | User Generated (UGC) |
## Video Start Delay
| Value | Description |
| ------- | ----------------------------------------------- |
| `>0` | Mid-Roll (value indicates start delay in seconds)|
| `0` | Pre-Roll |
| `-1` | Generic Mid-Roll |
| `-2` | Generic Post-Roll |
---
## Bid Request Examples(Request)
## Video Bid Request
Video Bid Request Example
```json title="Video Bid Request"
{
"app":
{
"bundle": "com.app.test",
"cat":
[
"IAB24"
],
"ext":
{
"badv":
[],
"bcat":
[],
"packagename": "com.appodeal.test"
},
"id": "1",
"name": "1 Test App",
"privacypolicy": 0,
"publisher":
{
"id": "1"
},
"storeurl": "http://play.google.com/app_url",
"ver": "1.0"
},
"at": 2,
"badv":
[],
"bcat":
[],
"device":
{
"carrier": "250-01",
"connectiontype": 2,
"devicetype": 4,
"ext":
{
"battery": 13,
"rooted": false
},
"geo":
{
"city": "New York",
"country": "USA",
"lat": 58.60169492,
"lon": 49.61514177,
"type": 1,
"utcoffset": 0,
"zip": "01010"
},
"h": 1788,
"hwv": "HUAWEI HUAWEI CAN-L11",
"ifa": "34a6eb23-ee34-47bb-9117-95aeb1156416",
"ip": "77.72.140.9",
"js": 1,
"language": "ru",
"lmt": 0,
"make": "HUAWEI",
"model": "HUAWEI HUAWEI CAN-L11",
"os": "Android",
"osv": "7.0",
"ppi": 480,
"pxratio": 3,
"ua": "Dalvik/2.1.0 (Linux; U; Android 7.0; HUAWEI CAN-L11Build/HUAWEICAN-L11)",
"w": 1080
},
"id": "87ad52d2-03cb-483a-a835-e391d3fde2b9",
"imp":
[
{
"bidfloor": 0.15,
"displaymanager": "mobilityware",
"displaymanagerver": "1.0.0",
"id": "643950c1-d9f3-458a-89e3-a04a60175315",
"instl": 1,
"video":
{
"api":
[
3,
5
],
"battr":
[
16
],
"delivery":
[
1,
2
],
"h": 480,
"linearity": 1,
"maxduration": 30,
"mimes":
[
"video/mp4"
],
"minduration": 5,
"playbackmethod":
[
1,
2,
3,
4
],
"protocols":
[
1,
2,
3,
4,
5,
6
],
"w": 320
}
}
],
"regs":
{
"coppa": 0,
"ext":
{
"gdpr": 0
}
},
"tmax": 300,
"user":
{
"gender": "M",
"geo":
{
"city": "New York",
"country": "USA",
"lat": 58.60169492,
"lon": 49.61514177,
"type": 1,
"utcoffset": 0,
"zip": "613045"
}
}
}
```
## Interstitial Bid Request
Interstitial Bid Request Example
```json title="Interstitial Bid Request"
{
"app":
{
"bundle": "com.app.test",
"cat":
[
"IAB24"
],
"ext":
{
"badv":
[],
"bcat":
[],
"packagename": "com.appodeal.test"
},
"id": "1",
"name": "1 Test App",
"privacypolicy": 0,
"publisher":
{
"id": "1"
},
"storeurl": "http://play.google.com/app_url",
"ver": "1.0"
},
"at": 2,
"badv":
[],
"bcat":
[],
"device":
{
"carrier": "250-01",
"connectiontype": 2,
"devicetype": 4,
"ext":
{
"battery": 13,
"rooted": false
},
"geo":
{
"city": "New York",
"country": "USA",
"lat": 58.60169492,
"lon": 49.61514177,
"type": 1,
"utcoffset": 0,
"zip": "613045"
},
"h": 1788,
"hwv": "HUAWEI HUAWEI CAN-L11",
"ifa": "34a6eb23-ee34-47bb-9117-95aeb1156416",
"ip": "77.72.140.9",
"js": 1,
"language": "ru",
"lmt": 0,
"make": "HUAWEI",
"model": "HUAWEI HUAWEI CAN-L11",
"os": "Android",
"osv": "7.0",
"ppi": 480,
"pxratio": 3,
"ua": "Dalvik/2.1.0 (Linux; U; Android 7.0; HUAWEI CAN-L11Build/HUAWEICAN-L11)",
"w": 1080
},
"id": "87ad52d2-03cb-483a-a835-e391d3fde2b9",
"imp":
[
{
"banner":
{
"api":
[
1,
2,
3,
4,
5
],
"h": 480,
"mimes":
[
"image/jpeg",
"image/jpg",
"image/gif",
"image/png"
],
"w": 320
},
"bidfloor": 0.15,
"displaymanager": "mobilityware",
"displaymanagerver": "1.0.0",
"id": "e5e98dc8-4085-4cc1-9fa7-34f0eadc2d27",
"instl": 1
}
],
"regs":
{
"coppa": 0,
"ext":
{
"gdpr": 0
}
},
"tmax": 300,
"user":
{
"gender": "M",
"geo":
{
"city": "New York",
"country": "USA",
"lat": 58.60169492,
"lon": 49.61514177,
"type": 1,
"utcoffset": 0,
"zip": "01010"
}
}
}
```
## Banner Bid Request
Banner Bid Request Example
```json title="Banner Bid Request"
{
"app":
{
"bundle": "com.app.test",
"cat":
[
"IAB24"
],
"ext":
{
"badv":
[],
"bcat":
[],
"packagename": "com.appodeal.test"
},
"id": "1",
"name": "1 Test App",
"privacypolicy": 0,
"publisher":
{
"id": "1"
},
"storeurl": "http://play.google.com/app_url",
"ver": "1.0"
},
"at": 2,
"badv":
[],
"bcat":
[],
"device":
{
"carrier": "250-01",
"connectiontype": 2,
"devicetype": 4,
"ext":
{
"battery": 13,
"rooted": false
},
"geo":
{
"city": "New York",
"country": "USA",
"lat": 58.60169492,
"lon": 49.61514177,
"type": 1,
"utcoffset": 0,
"zip": "01010"
},
"h": 1788,
"hwv": "HUAWEI HUAWEI CAN-L11",
"ifa": "34a6eb23-ee34-47bb-9117-95aeb1156416",
"ip": "77.72.140.9",
"js": 1,
"language": "ru",
"lmt": 0,
"make": "HUAWEI",
"model": "HUAWEI HUAWEI CAN-L11",
"os": "Android",
"osv": "7.0",
"ppi": 480,
"pxratio": 3,
"ua": "Dalvik/2.1.0 (Linux; U; Android 7.0; HUAWEI CAN-L11Build/HUAWEICAN-L11)",
"w": 1080
},
"id": "87ad52d2-03cb-483a-a835-e391d3fde2b9",
"imp":
[
{
"banner":
{
"api":
[
1,
2,
3,
4,
5
],
"h": 50,
"mimes":
[
"image/jpeg",
"image/jpg",
"image/gif",
"image/png"
],
"w": 320
},
"bidfloor": 0.01,
"displaymanager": "mobilityware",
"displaymanagerver": "1.0.0",
"id": "e5e98dc8-4085-4cc1-9fa7-34f0eadc2d27",
"instl": 0
}
],
"regs":
{
"coppa": 0,
"ext":
{
"gdpr": 0
}
},
"tmax": 300,
"user":
{
"gender": "M",
"geo":
{
"city": "New York",
"country": "USA",
"lat": 58.60169492,
"lon": 49.61514177,
"type": 1,
"utcoffset": 0,
"zip": "01010"
}
}
}
```
---
## Bid Request Specification(Request)
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import JavaLabel from "@site/src/components/code-labels/java";
import KotlinLabel from "@site/src/components/code-labels/kotlin";
import SwiftLabel from "@site/src/components/code-labels/swift";
import ObjCLabel from "@site/src/components/code-labels/objc";
The following page describes the fields of the `BidRequest` object:
## Request
| Attribute | Type | Description | Example |
|-----------|------------------------------------|------------------------------------------------------------------------------------------------------------------------|---------------------------------------|
| `id` | optional, string | Unique ID of the bid request, provided by the exchange. | `d5260eec-75d9-4f7d-86bc-22b01b4c779e` |
| `imp` | required, object[] | Array of `Imp` objects representing the impressions offered. Must contain at least one item. | *(array of Imp objects)* |
| `app` | required, object | Details about the publisher’s app (non-browser applications). Recommended for in-app traffic. | *(App object)* |
| `device` | required, object | Details about the user’s device to which the impression will be delivered. | *(Device object)* |
| `user` | required, object | Details about the human user of the device (the advertising audience). | *(User object)* |
| `test` | optional, integer (default `0`) | Test mode flag: `0` = live mode, `1` = test mode (non-billable). | `0` |
| `at` | optional, integer (default `1`) | Auction type: `1` = First-Price, `2` = Second-Price Plus (BidMachine supports only `1`). | `1` |
| `cur` | optional, string[] (default `["USD"]`) | Array of allowed currencies (ISO-4217 codes). Recommended if multiple currencies are supported. Default is `["USD"]`. | `['USD']` |
| `bcat` | optional, string[] | Blocked advertiser categories using the IAB content taxonomy. | `['IAB2-1']` |
| `badv` | optional, string[] | Block list of advertiser domains. | `['blocked.domain']` |
| `regs` | optional, object | `Regs` object specifying industry, legal, or governmental regulations for this request. | *(Regs object)* |
## Imp Object
| Attribute | Type | Description | Example |
|---------------------|---------------------------|--------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------|
| `id` | required, string | A unique identifier for this impression within the context of the bid request (typically, starts with 1 and increments or a UUID). | `6ba06f9a-44c8-497d-8bc3-78804bebc2c8` |
| `banner` | object | Banner object; required if this impression is offered as a banner ad opportunity. | *(Banner object)* |
| `video` | object | Video object; required if this impression is offered as a video ad opportunity. | *(Video object)* |
| `native` | object | Native object; required if this impression is offered as a native ad opportunity. | *(Native object)* |
| `displaymanager` | required, string | Name of ad mediation partner, SDK technology, or player responsible for rendering the ad. Recommended for video and in-app SDKs. | `you_ssp_name` |
| `displaymanagerver` | required, string | Version of the ad mediation partner or SDK. Recommended for video and in-app SDKs. | `2.0.0` |
| `instl` | optional, integer (default `0`) | `1` = interstitial/fullscreen, `0` = banner. | `0` |
| `tagid` | optional, string | Identifier for the ad placement or tag used to initiate the auction. Useful for debugging and optimization. | `my__debug__tag` |
| `bidfloor` | required, number (default `0`) | Minimum bid for this impression expressed in CPM. | `0.15` |
| `bidfloorcur` | optional, string (default `"USD"`) | Currency for the `bidfloor` (ISO-4217). May differ from bid response currency if allowed. | `USD` |
## Banner Object
| Attribute | Type | Description | Example |
|-----------|----------------|------------------------------------------------------------------------------------------------------------------------------------|-------------------------------|
| `w` | integer | Width of the impression in pixels. If neither `wmin` nor `wmax` are specified, this value is an exact width requirement. Otherwise, it is a preferred width. | `320` |
| `h` | integer | Height of the impression in pixels. If neither `hmin` nor `hmax` are specified, this value is an exact height requirement. Otherwise, it is a preferred height. | `50` |
| `wmax` | integer | Maximum width of the impression in pixels. If included with `w`, then `w` is treated as preferred width. | `320` |
| `hmax` | integer | Maximum height of the impression in pixels. If included with `h`, then `h` is treated as preferred height. | `50` |
| `wmin` | integer | Minimum width of the impression in pixels. If included with `w`, then `w` is treated as preferred width. | `320` |
| `hmin` | integer | Minimum height of the impression in pixels. If included with `h`, then `h` is treated as preferred height. | `50` |
| `id` | string | Unique identifier for this banner object. Recommended for companion ads; values unique within an impression. | `ap1gm-0jioruind-1ffopjgo1p` |
| `btype` | integer[] | Blocked banner ad types. | `[2]` |
| `battr` | integer[] | Blocked creative attributes. Appodeal currently blocks: Expandable (User Initiated – Rollover), Pop (Over/Under/Exit), Suggestive Imagery, Shaky/Flashing/Animated, Windows Dialog Style. | `[5,8,9,10,14]` |
| `pos` | integer | Ad position on screen. | `5` |
| `mimes` | string[] | Supported MIME types (e.g., `image/png`, `image/jpg`, `image/gif`). | `['image/jpg','image/gif','image/png']` |
| `topframe`| integer | Top-frame flag: `0` = no, `1` = yes. | `1` |
| `api` | integer[] | List of supported API frameworks. Unlisted APIs are assumed unsupported. | `[5,3]` |
## Video Object
| Attribute | Type | Description | Example |
|----------------|----------------|-------------------------------------------------------------------------------------------------------------------------------|-----------------|
| `mimes` | string[] | Content MIME types supported. | `['video/mp4']` |
| `minduration` | integer | Minimum video ad duration in seconds. | `5` |
| `maxduration` | integer | Maximum video ad duration in seconds. | `30` |
| `protocol` | integer | Supported video bid response protocol (use `protocols` when possible). At least one must be specified in `protocol` or `protocols`. | `1` |
| `protocols` | integer[] | Array of supported video bid response protocols. | `[1,2,6]` |
| `w` | integer | Width of the video player in pixels. | `320` |
| `h` | integer | Height of the video player in pixels. | `480` |
| `startdelay` | integer | Start delay in seconds for pre-roll, mid-roll, or post-roll ad placements. | `1` |
| `linearity` | integer | Impression linearity: `1` = linear, `2` = non-linear. If unspecified, assume all allowed. | `1` |
| `battr` | integer[] | Blocked creative attributes. **IMPORTANT:** for rewarded video, send `[16]` here. | `[1,3]` |
| `minbitrate` | integer | Minimum bit rate in Kbps. | `128` |
| `maxbitrate` | integer | Maximum bit rate in Kbps. | `512` |
| `playbackmethod`| integer[] | Allowed playback methods. If none specified, assume all are allowed. | `[1,2,3,4]` |
| `delivery` | integer[] | Supported delivery methods (e.g., streaming, progressive). If none specified, assume all supported. | `[1,2]` |
| `pos` | integer | Ad position on screen. | `3` |
| `companiodad` | object[] | Companion banner objects (if companion ads are available). | *(empty)* |
| `api` | integer[] | Supported API frameworks. Unlisted APIs are assumed unsupported. | `[1,2,3,4,5]` |
| `companiontype`| integer[] | Supported VAST companion ad types. Recommended if companion banners are used. | `[1]` |
## Native Object
| Attribute | Type | Description | Example |
|-----------|----------------|------------------------------------------------------------------------------------------------------|-----------------|
| `request` | string | Request payload complying with the Native Ad Specification. | `"89oghjnr"` |
| `ver` | string | Version of the Native Ad Specification to which the request complies; recommended for efficient parsing. | `"1.0"` |
| `api` | integer[] | List of supported API frameworks for this impression. If an API is not explicitly listed, it is assumed unsupported. | `[1]` |
| `battr` | integer[] | Blocked creative attributes. | `[5,3]` |
## App Object
| Attribute | Type | Description | Example |
|--------------|-------------------|-------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|
| `id` | required, string | Exchange-specific app ID. | `"102938"` |
| `name` | required, string | App name (may be aliased at the publisher’s request). | `"MyApp"` |
| `bundle` | required, string | Application bundle or package name (e.g., `com.app.game`); intended to be a unique ID across exchanges. iOS passes the **App Store ID**, Android passes the **package name**. | Android: `"com.appodeal.test"`, iOS: `"78945611"` |
| `domain` | optional, string | Domain of the app. | `"game.app.com"` |
| `storeurl` | optional, string | App store URL for an installed app; for QAG 1.5 compliance. | `"https://itunes.apple.com/..id1234"`|
| `cat` | optional, string[]| Array of IAB content categories of the app. | `['IAB2-1', 'IAB2-4']` |
| `sectioncat` | optional, string[]| Array of IAB content categories describing the current section of the app. | `['IAB2']` |
| `pagecat` | optional, string[]| Array of IAB content categories describing the current page or view of the app. | `['IAB2-1']` |
| `ver` | optional, string | Application version. | `"1.0.3"` |
| `privacypolicy`| optional, integer| Privacy policy flag: `0` = no, `1` = yes. | `1` |
| `paid` | optional, integer | App cost flag: `0` = free, `1` = paid. | `1` |
| `publisher` | optional, object | Details about the publisher of the app. | *(empty)* |
| `keywords` | optional, string | Comma-separated list of keywords about the app. | `"automotive"` |
| `ext` | optional, object | Placeholder for exchange-specific extensions to OpenRTB. | *(empty)* |
## Device Object
| Attribute | Type | Description | Example |
|------------------|--------------------|---------------------------------------------------------------------------------------------------------|-------------------------------------------------|
| `ua` | optional, string | Browser user agent string. | `"Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X) AppleWebKit/602.3.12 (KHTML, like Gecko) Mobile/14C89"` |
| `geo` | required, object | Location of the device assumed to be the user’s current location defined by a Geo object. | *(Geo object)* |
| `dnt` | optional, integer | Standard “Do Not Track” flag: `0` = unrestricted, `1` = do not track. | `0` |
| `lmt` | optional, integer | “Limit Ad Tracking” signal: `0` = unrestricted, `1` = limited. | `1` |
| `ip` | optional, string | IPv4 address closest to device. | `23.227.207.23` |
| `ipv6` | optional, string | IPv6 address closest to device. | `2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d` |
| `devicetype` | optional, integer | The general type of device. | `4` |
| `make` | optional, string | Device make. | `"Apple"` |
| `model` | optional, string | Device model. | `"iPhone"` |
| `os` | required, string | Device operating system. | `"iOS"` |
| `osv` | optional, string | Device operating system version. | `"10.1.3"` |
| `hwv` | required, string | Hardware version of the device. | `"5S"` |
| `h` | optional, integer | Physical height of the screen in pixels. | `568` |
| `w` | optional, integer | Physical width of the screen in pixels. | `320` |
| `ppi` | optional, integer | Screen size in pixels per linear inch. | `326` |
| `pxratio` | optional, float | Ratio of physical pixels to device-independent pixels. | `2` |
| `js` | optional, integer | Support for JavaScript: `0` = no, `1` = yes. | `1` |
| `language` | optional, string | Browser language (ISO-639-1-alpha-2). | `"en"` |
| `carrier` | optional, string | Carrier or ISP (e.g., “VERIZON”). “WIFI” indicates high bandwidth. | *(empty)* |
| `connectiontype` | optional, integer | Network connection type. | `2` |
| `ifa` | optional, string | ID sanctioned for advertiser use in the clear (not hashed). | `382A78A3-7EA0-4D3B-9724-0231C07D0C5A` |
## User Object
| Attribute | Type | Description | Example |
|------------|---------------------|------------------------------------------------------------------------------------------------------------------------------------|----------------|
| `id` | recommended, string | Exchange-specific ID for the user. At least one of `id` or `buyerid` is recommended. | `"1"` |
| `yob` | optional, integer | Year of birth as a 4-digit integer. | `1984` |
| `gender` | optional, string | Gender: `"M"` = male, `"F"` = female, `"O"` = other (omitted = unknown). | `"O"` |
| `keywords` | optional, string | Comma-separated list of keywords, interests, or intent. | `"game"` |
| `geo` | optional, object | Location of the user’s home base defined by a Geo object. Not necessarily their current location. | *(Geo object)* |
## Geo Object
| Attribute | Type | Description | Example |
|-------------|---------|-----------------------------------------------------------------|----------|
| `lat` | float | Latitude from -90.0 to +90.0, where negative is south. | `15` |
| `lon` | float | Longitude from -180.0 to +180.0, where negative is west. | `30` |
| `type` | integer | Source of location data; recommended when passing lat/lon. | `2` |
| `country` | string | Country code using ISO-3166-1-alpha-3. | `"USA"`|
| `city` | string | City using United Nations Code for Trade & Transport Locations. See Appendix A for a link to the codes. | `"New York"`|
| `zip` | string | Zip or postal code. | `"19809"`|
| `utcoffset` | integer | Local time as the number +/- of minutes from UTC. | `180` |
## Regs Object
| Attribute | Type | Description | Example |
|-----------|------------------|--------------------------------------------------------------------------------------------------------------|---------|
| `coppa` | optional, integer| Flag indicating if this request is subject to COPPA regulations (USA FTC), where `0` = no, `1` = yes. | `0` |
| `ext` | optional, object | Ext object for GDPR in OpenRTB 2.2–2.5. | *(see below)* |
**Regs.ext:**
| Attribute | Type | Description | Example |
|-----------|------------------|----------------------------------------------------------------------------------------------------|---------|
| `gdpr` | optional, integer| Signals if the request is subject to GDPR regulations: `0` = No, `1` = Yes. | `0` |
---
## Examples
## Video Bid Response
VAST Bid Response Example
```json title="VAST Bid Response"
{
"cur": "USD",
"id": "73b4f887-5274-4424-9dae-599e49edebce",
"seatbid":
[
{
"bid":
[
{
"adm": "\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n RubiconProject\n \n \n \n \n \n \n \n \n \n \n Portrait\n \n \n \n\nc993d46a-d393-46e9-97c8-2fca0319802b\n0.120276\n\n2723942\n\n182267252\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n ",
"crid": "2249:182267252",
"h": 480,
"id": "18c38bd6-0763-4487-bb9e-5d637c2d90e9",
"impid": "bd67f974-1e64-4035-a502-01565f151959",
"price": 0.0926,
"w": 320
}
],
"group": 0
}
]
}
```
## Interstitial Bid Response
HTML Interstitial Bid Response Example
```json title="Interstitial Bid Response"
{
"cur": "USD",
"id": "1561986473007-d6a023a4-b23a-4d14-ad90-87b56096b536",
"seatbid":
[
{
"bid":
[
{
"adm": "\n\n \n",
"cid": "44571",
"crid": "u5d0c48d1100aa9",
"h": 480,
"id": "18971e3c-0567-4a19-931c-b65cb6be49df",
"impid": "d6a023a4-b23a-4d14-ad90-87b56096b536-2",
"lurl": "https://api.appodealx.com/track/lurl/interstitial?context=eyJiaWRSZXF1ZXN0SWQiOiI1MDBhZDViMy1iNmI0LTRkZjctYWI3NC0wNzAyY2RlZTRmYWUiLCJvcmlnaW5hbEJpZEZsb29yIjowLjAxLCJiaWRGbG9vciI6MC4wMSwiYmlkUHJpY2UiOjAuMDY0LCJjbGVhcmluZ1ByaWNlIjowLjAyLCJleGNoYW5nZUZlZSI6MC4wMDQ2LCJzc3BJbmNvbWUiOjAuMDE1NCwidGltZXN0YW1wIjoiMjAxOS0wNy0wNFQxMTo1Njo1Ni4yMzhaIiwiYXBwQnVuZGxlIjoiMzU5OTE3NDE0IiwiYXBwSWRSYXciOiI1MGI4NmE3OGVhNjg0ZTg3NmJkZDg0ZTE1MTQ0MjgxOCIsImFwcE5hbWUiOiJDb3JlYWRlci0gUVIgQ29kZSAmIEJhcmNvZGUgU2Nhbm5lciIsInNzcEF1Y3Rpb25UeXBlIjoxLCJjb3VudHJ5IjoiVVMiLCJkZXZpY2VPcyI6ImlvcyIsImRldmljZU9zVmVyc2lvbiI6IjkiLCJkZXZpY2VJcCI6IjQ3LjExLjEzNC4xMTUiLCJkZXZpY2VDb25uZWN0aW9uVHlwZSI6NiwiYWRUeXBlIjoiaW50ZXJzdGl0aWFsIiwiYWRTaXplIjoiMzIweDQ4MCIsImFnZW5jeUlkIjo1MiwiZXh0ZXJuYWxBZ2VuY3lJZCI6OTg3OSwiaWZhIjoiYWI2YjllYzEtZWE3Mi00NmI4LTk4ZGEtODdjNGZkNDgzNjc3IiwiYWdlbmN5TmFtZSI6IkJ1Y2tzZW5zZSIsImJpZGRlck5hbWUiOiJCdWNrc2Vuc2UgYmlkZGVyIiwic2RrTmFtZSI6ImNvb3RlayIsInNka1ZlcnNpb24iOiIxLjAuMCIsImRpc3BsYXlNYW5hZ2VyIjoibXJhaWQiLCJhZG9tYWluIjpbIlBSSUNFTE9PU0UuQ09NIl0sImNpZCI6IjQ0NTcxIiwiY3JpZCI6InU1ZDBjNDhkMTEwMGFhOSIsImlzTmV3U2RrVmVyc2lvbiI6ZmFsc2UsInNlbGxlcklkIjoxLCJzZWxsZXJOYW1lIjoiQXBwb2RlYWwgU1NQIiwiYWROZXR3b3JrIjpmYWxzZSwicmV3YXJkIjpmYWxzZX0%3D&trm=11&token=b323c4c38cc808827304eaca415ab1a315e74182acfe1b18f58f3bf41e1f2122&ssp_clear_price=${AUCTION_PRICE}&trackers=W10%3D",
"nurl": "https://api.appodealx.com/track/nurl/interstitial?context=eyJiaWRSZXF1ZXN0SWQiOiI1MDBhZDViMy1iNmI0LTRkZjctYWI3NC0wNzAyY2RlZTRmYWUiLCJvcmlnaW5hbEJpZEZsb29yIjowLjAxLCJiaWRGbG9vciI6MC4wMSwiYmlkUHJpY2UiOjAuMDY0LCJjbGVhcmluZ1ByaWNlIjowLjAyLCJleGNoYW5nZUZlZSI6MC4wMDQ2LCJzc3BJbmNvbWUiOjAuMDE1NCwidGltZXN0YW1wIjoiMjAxOS0wNy0wNFQxMTo1Njo1Ni4yMzhaIiwiYXBwQnVuZGxlIjoiMzU5OTE3NDE0IiwiYXBwSWRSYXciOiI1MGI4NmE3OGVhNjg0ZTg3NmJkZDg0ZTE1MTQ0MjgxOCIsImFwcE5hbWUiOiJDb3JlYWRlci0gUVIgQ29kZSAmIEJhcmNvZGUgU2Nhbm5lciIsInNzcEF1Y3Rpb25UeXBlIjoxLCJjb3VudHJ5IjoiVVMiLCJkZXZpY2VPcyI6ImlvcyIsImRldmljZU9zVmVyc2lvbiI6IjkiLCJkZXZpY2VJcCI6IjQ3LjExLjEzNC4xMTUiLCJkZXZpY2VDb25uZWN0aW9uVHlwZSI6NiwiYWRUeXBlIjoiaW50ZXJzdGl0aWFsIiwiYWRTaXplIjoiMzIweDQ4MCIsImFnZW5jeUlkIjo1MiwiZXh0ZXJuYWxBZ2VuY3lJZCI6OTg3OSwiaWZhIjoiYWI2YjllYzEtZWE3Mi00NmI4LTk4ZGEtODdjNGZkNDgzNjc3IiwiYWdlbmN5TmFtZSI6IkJ1Y2tzZW5zZSIsImJpZGRlck5hbWUiOiJCdWNrc2Vuc2UgYmlkZGVyIiwic2RrTmFtZSI6ImNvb3RlayIsInNka1ZlcnNpb24iOiIxLjAuMCIsImRpc3BsYXlNYW5hZ2VyIjoibXJhaWQiLCJhZG9tYWluIjpbIlBSSUNFTE9PU0UuQ09NIl0sImNpZCI6IjQ0NTcxIiwiY3JpZCI6InU1ZDBjNDhkMTEwMGFhOSIsImlzTmV3U2RrVmVyc2lvbiI6ZmFsc2UsInNlbGxlcklkIjoxLCJzZWxsZXJOYW1lIjoiQXBwb2RlYWwgU1NQIiwiYWROZXR3b3JrIjpmYWxzZSwicmV3YXJkIjpmYWxzZX0%3D&trm=11&token=b323c4c38cc808827304eaca415ab1a315e74182acfe1b18f58f3bf41e1f2122&ssp_clear_price=${AUCTION_PRICE}&trackers=W10%3D",
"price": 0.0154,
"w": 320
}
],
"group": 0
}
]
}
```
## Banner Bid Response
Banner Bid Response Example
```json title="Banner Bid Response"e
{
"cur": "USD",
"id": "1561986473007-d6a023a4-b23a-4d14-ad90-87b56096b536",
"seatbid":
[
{
"bid":
[
{
"adm": "\n\n \n",
"cid": "26562",
"crid": "6385303",
"h": 50,
"id": "bc73f0a0-269d-449e-9e41-159aa9e922e2",
"impid": "d6a023a4-b23a-4d14-ad90-87b56096b536-2",
"lurl": "https://api.appodealx.com/track/lurl/banner?context=eyJiaWRSZXF1ZXN0SWQiOiI3OWE5OTM4Ni1jMjY4LTRjY2YtOTU5Yi00OWM2NDg1MWJhODIiLCJvcmlnaW5hbEJpZEZsb29yIjowLjAxLCJiaWRGbG9vciI6MC4wMSwiYmlkUHJpY2UiOjAuMTcsImNsZWFyaW5nUHJpY2UiOjAuMDIsImV4Y2hhbmdlRmVlIjowLjAwNDYsInNzcEluY29tZSI6MC4wMTU0LCJ0aW1lc3RhbXAiOiIyMDE5LTA3LTA0VDExOjU3OjU0Ljg2MFoiLCJhcHBCdW5kbGUiOiIzNTk5MTc0MTQiLCJhcHBJZFJhdyI6IjUwYjg2YTc4ZWE2ODRlODc2YmRkODRlMTUxNDQyODE4IiwiYXBwTmFtZSI6IkNvcmVhZGVyLSBRUiBDb2RlICYgQmFyY29kZSBTY2FubmVyIiwic3NwQXVjdGlvblR5cGUiOjEsImNvdW50cnkiOiJVUyIsImRldmljZU9zIjoiaW9zIiwiZGV2aWNlT3NWZXJzaW9uIjoiOSIsImRldmljZUlwIjoiNDcuMTEuMTM0LjExNSIsImRldmljZUNvbm5lY3Rpb25UeXBlIjo2LCJhZFR5cGUiOiJiYW5uZXIiLCJhZFNpemUiOiIzMjB4NTAiLCJhZ2VuY3lJZCI6NjUsImV4dGVybmFsQWdlbmN5SWQiOjExMzAwLCJpZmEiOiJhYjZiOWVjMS1lYTcyLTQ2YjgtOThkYS04N2M0ZmQ0ODM2NzciLCJhZ2VuY3lOYW1lIjoiSmFtcHAiLCJiaWRkZXJOYW1lIjoiSmFtcHAgYmlkZGVyIiwic2RrTmFtZSI6ImNvb3RlayIsInNka1ZlcnNpb24iOiIxLjAuMCIsImRpc3BsYXlNYW5hZ2VyIjoibXJhaWQiLCJhZG9tYWluIjpbImF1ZGlibGVhcHBsaWNhdGlvbi5jb20iXSwiY2lkIjoiMjY1NjIiLCJjcmlkIjoiNjM4NTMwMyIsImlzTmV3U2RrVmVyc2lvbiI6ZmFsc2UsInNlbGxlcklkIjoxLCJzZWxsZXJOYW1lIjoiQXBwb2RlYWwgU1NQIiwiYWROZXR3b3JrIjpmYWxzZSwicmV3YXJkIjpmYWxzZX0%3D&trm=11&token=41eeb579af2fbc99f0e3c0e0f90c266fa744318a9c985e8146f03466d6022c92&ssp_clear_price=${AUCTION_PRICE}&trackers=W10%3D",
"nurl": "https://api.appodealx.com/track/nurl/banner?context=eyJiaWRSZXF1ZXN0SWQiOiI3OWE5OTM4Ni1jMjY4LTRjY2YtOTU5Yi00OWM2NDg1MWJhODIiLCJvcmlnaW5hbEJpZEZsb29yIjowLjAxLCJiaWRGbG9vciI6MC4wMSwiYmlkUHJpY2UiOjAuMTcsImNsZWFyaW5nUHJpY2UiOjAuMDIsImV4Y2hhbmdlRmVlIjowLjAwNDYsInNzcEluY29tZSI6MC4wMTU0LCJ0aW1lc3RhbXAiOiIyMDE5LTA3LTA0VDExOjU3OjU0Ljg2MFoiLCJhcHBCdW5kbGUiOiIzNTk5MTc0MTQiLCJhcHBJZFJhdyI6IjUwYjg2YTc4ZWE2ODRlODc2YmRkODRlMTUxNDQyODE4IiwiYXBwTmFtZSI6IkNvcmVhZGVyLSBRUiBDb2RlICYgQmFyY29kZSBTY2FubmVyIiwic3NwQXVjdGlvblR5cGUiOjEsImNvdW50cnkiOiJVUyIsImRldmljZU9zIjoiaW9zIiwiZGV2aWNlT3NWZXJzaW9uIjoiOSIsImRldmljZUlwIjoiNDcuMTEuMTM0LjExNSIsImRldmljZUNvbm5lY3Rpb25UeXBlIjo2LCJhZFR5cGUiOiJiYW5uZXIiLCJhZFNpemUiOiIzMjB4NTAiLCJhZ2VuY3lJZCI6NjUsImV4dGVybmFsQWdlbmN5SWQiOjExMzAwLCJpZmEiOiJhYjZiOWVjMS1lYTcyLTQ2YjgtOThkYS04N2M0ZmQ0ODM2NzciLCJhZ2VuY3lOYW1lIjoiSmFtcHAiLCJiaWRkZXJOYW1lIjoiSmFtcHAgYmlkZGVyIiwic2RrTmFtZSI6ImNvb3RlayIsInNka1ZlcnNpb24iOiIxLjAuMCIsImRpc3BsYXlNYW5hZ2VyIjoibXJhaWQiLCJhZG9tYWluIjpbImF1ZGlibGVhcHBsaWNhdGlvbi5jb20iXSwiY2lkIjoiMjY1NjIiLCJjcmlkIjoiNjM4NTMwMyIsImlzTmV3U2RrVmVyc2lvbiI6ZmFsc2UsInNlbGxlcklkIjoxLCJzZWxsZXJOYW1lIjoiQXBwb2RlYWwgU1NQIiwiYWROZXR3b3JrIjpmYWxzZSwicmV3YXJkIjpmYWxzZX0%3D&trm=11&token=41eeb579af2fbc99f0e3c0e0f90c266fa744318a9c985e8146f03466d6022c92&ssp_clear_price=${AUCTION_PRICE}&trackers=W10%3D",
"price": 0.0154,
"w": 320
}
],
"group": 0
}
]
}
```
---
## Testing Environment
## Endpoint
Use the following testing endpoint for bid requests:
[`https://api.appodealx.com/ssp/1/auction`](https://api.appodealx.com/ssp/1/auction)
## Bid Floor
When testing, set the minimum bid floor to `0.01` (CPM).
:::note
Fill rate may not reach 100% in the testing environment.
:::
---
## Console Setup(Topon)
import Image from "@theme/IdealImage";
This page describes how to set up the BidMachine ad platform within your existing TopOn mediation.
## Step 1. Obtain BidMachine Credentials
You need to obtain the following credentials from your BidMachine account:
| **Parameter Name** | **Description** |
| ------------------ | --------------- |
| Source ID | Required for ad requests |
| Account ID | Required for Report API ad data |
| Account Password | Required for Report API ad data |
## Step 2. Configure BidMachine in TopOn Dashboard
### Add Ad Source
1. Log in to the TopOn dashboard
2. Navigate to **Ad Platforms** → **Ad Source Management**
3. Locate **BidMachine** in the list
4. Click **Add Ad Source**
5. Fill in the following parameters:
- **Source ID**: Enter the Source ID obtained in Step 1
- **Account ID**: Enter the Account ID for Report API access
- **Account Password**: Enter the Account password for Report API access
6. Click **Save**
:::note
There is no need to create app and placement in the BidMachine dashboard. However, you will need to create a placement ID in the TopOn dashboard to distinguish advertising data.
:::
### Add Ad Source to Mediation
1. Navigate to **Mediation** in TopOn dashboard
2. Click **Add Ad Source**
3. Select **BidMachine** from the available ad sources
4. Configure the placement:
- **Custom Placement ID**: Enter a custom placement ID for advertisement data differentiation (this can be any string to help you identify the placement)
5. Save your configuration
## Step 3. Add BidMachine Adapter to Your Application
After configuring BidMachine in the TopOn dashboard, you need to integrate the BidMachine adapter into your application code.
Refer to the [TopOn SDK integration documentation](https://help.toponad.net/docs/cUkkAX) for complete integration instructions.
---
## Overview(Topon)
BidMachine adapter allows you to use the BidMachine ad platform within your existing TopOn mediation. BidMachine supports banner, native, interstitial and rewarded video ads.
:::info
TopOn SDK v6.4.56 and above is required to use BidMachine network.
:::
## Supported Features
| **Platform** | **Bidding Type** | **Ad Formats** |
| ------------ | ---------------- | -------------- |
| Android/iOS | Waterfall, S2S | Banner, Native, Rewarded Video, Interstitial |
## How to Create a BidMachine Account
1. Create a BidMachine Account at [bidmachine.io](https://bidmachine.io/#sign-up).
2. Upon registration, an activation email containing instructions will be sent to the email address you've provided. Please use the provided instructions to activate your account.
3. Contact BidMachine (email: hi@bidmachine.io) to apply for an account if needed.
4. To enable BidMachine Ad Inventory through the TopOn Mediation platform, you must have an approved monetization account with BidMachine.
## How to Get Source ID
The Source ID can only be provided by the BidMachine representative. You must contact them to receive your Source ID, which is required for ad requests.
In order to get Source ID, please refer to this guide - [How to get Source ID under BidMachine Dashboard](/dashboard/source).
## Enable BidMachine in Your TopOn Account
[How to Enable BidMachine in TopOn Dashboard](/sdk/topon/console-setup)
## How to Create a TopOn Account
In case you don't have a TopOn account, please visit [TopOn's official website](https://www.toponad.net/) to register and create your account.
## Integration Types
BidMachine supports the following integration types with TopOn:
- **Android Adapter** - Integrate BidMachine adapter on Android
- **iOS Adapter** - Integrate BidMachine adapter on iOS
## Integration Documentation
For detailed TopOn SDK integration, please refer to the [TopOn SDK integration documentation](https://docs.toponad.com/).