Integration
Add your app in the dashboard and create a placement. You get a placement key starting with pk_. Ads start once your app is approved.
Telegram Mini App
Add the script and show a placement. User and language come from Telegram automatically. Pass a container for banner and push-style ads; full-screen formats open on their own.
<script src="https://telegram.org/js/telegram-web-app.js"></script>
<script src="https://cleanads.ai/sdk/v1.js"></script>
<div id="ad"></div>
<script>
// Banner or push-style
CleanAds.show("pk_PLACEMENT", "#ad");
// Rewarded
CleanAds.show("pk_REWARDED").then(function (result) {
if (result.rewarded) unlockReward(result.tx);
});
</script>If you save your bot token in the dashboard, every request is verified against Telegram's signature and forged ones are refused.
Telegram bot
Request an ad from your bot's server, send it to the user, then report the impression. Keep the server key on your server only.
import requests
SECRET = "sk_..."
HEADERS = {"x-cleanads-secret": SECRET}
ad = requests.get("https://cleanads.ai/api/v1/ad",
params={"placement": "pk_PLACEMENT", "user": telegram_user_id, "lang": "tr"},
headers=HEADERS).json()["ad"]
if ad:
bot.send_message(chat_id, f"{ad['title']}\n{ad['body']}\n\nAd",
reply_markup=url_button(ad["cta"], ad["click_url"]))
requests.post(ad["impression_url"], headers=HEADERS)iOS
SDK source lives in the sdks folder of the repository.
import CleanAds
CleanAds.initialize(userId: currentUser.id)
if let ad = await CleanAds.load("pk_PLACEMENT") {
present(CleanAdsFullscreenController(ad: ad), animated: true)
}
// Banner
let banner = CleanAdsBannerView()
banner.load(placementKey: "pk_BANNER")Android
CleanAds.init(userId = user.id)
CleanAds.load("pk_PLACEMENT") { ad ->
if (ad != null) CleanAdsFullscreenActivity.show(context, ad, onReward = { grantInUi() })
}
// Banner
findViewById<CleanAdsBannerView>(R.id.banner).load("pk_BANNER")Flutter
CleanAds.init(userId: user.id, openUrl: (uri) => launchUrl(uri));
final ad = await CleanAds.load('pk_PLACEMENT');
if (ad != null) await showCleanAdsFullscreen(context, ad);
// Banner
CleanAdsBanner(placementKey: 'pk_BANNER')React Native
import { init, CleanAdsBanner } from "cleanads-react-native";
init({ userId: user.id });
<CleanAdsBanner placement="pk_BANNER" />HTTP API
Three calls are enough to write your own client.
- Request an ad. On no fill, ad is null.
- POST once to impression_url when the ad is on screen.
- Open click_url in the system browser on tap.
GET https://cleanads.ai/api/v1/ad?placement=pk_PLACEMENT&user=USER_ID&lang=tr
{
"ad": {
"format": "native",
"label": "Ad",
"title": "...", "body": "...", "cta": "Open",
"icon": "https://...", "image": null, "video": null,
"impression_url": "https://cleanads.ai/api/v1/imp?t=...",
"click_url": "https://cleanads.ai/api/v1/click?t=...",
"complete_url": null
}
}Always show the ad with its ad.label tag.
Reward callback
When a rewarded ad finishes, the URL you set in the dashboard receives a signed request. Grant the reward from your server on this request, never from the client. Process each tx once.
// GET your-url?placement=&user_id=&reward=&amount=&tx=&ts=&sig=
const canonical = [placement, user_id, reward, amount, tx, ts].join(".");
const expected = crypto.createHmac("sha256", SERVER_SECRET).update(canonical).digest("hex");
if (crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig))) grantOnce(tx);Conversion postback
Add {click_id} to your destination URL and call this from your server on conversion. The full URL is ready on your campaign page.
GET https://cleanads.ai/api/v1/postback?key=pb_KEY&click_id=CLICK_ID&event=install&value=1.50app-ads.txt
For mobile apps, add this line to app-ads.txt at the root of your developer site. Your publisher id is on your app page.
cleanads.ai, pub-XXXXXXXXXXXXXXXX, DIRECT