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.

  1. Request an ad. On no fill, ad is null.
  2. POST once to impression_url when the ad is on screen.
  3. 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.50

app-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