Developer Documentation

Everything you need to
integrate AmanahAds

One page covering setup, ad types, integration code, targeting, the API, and payouts — from creating your first instance to your first cashout.

Overview

AmanahAds connects two sides: advertisers who create campaigns and pay to reach an audience, and developers (publishers) who embed ad slots on their website or app and earn a share of what advertisers pay.

The flow, end to end:

  1. An advertiser creates a campaign — picks an ad type/size, uploads a creative, sets a budget and (optionally) an audience — and it goes live once approved and paid for.
  2. A developer registers a site or app instance, declares which ad type/size slots it supports, and gets an API key.
  3. The developer embeds a small snippet (iframe or script) using that key.
  4. Every time a real visitor loads the page, AmanahAds matches an eligible campaign to that slot and serves it.
  5. The developer earns a share of the impression/click/reward value (commission split explained in Earnings & Payouts), held for a few days, then cashable out via bKash.

Quick Start

  1. Sign up as a developer and go to Instances → New Instance.
  2. Register your site or app — pick Website (give your URL) or App (platform + package name/bundle ID).
  3. Add supported ad types — pick from Banner, Video, Interstitial, or Rewarded, each paired with a size (see Ad Types).
  4. Copy your key — every instance gets a Development key (works everywhere, no verification needed — use this while testing) and a Production key (only works on your registered domain, needs admin verification before it serves ads).
  5. Embed the snippet — from the instance's "Get Code" button, or copy the patterns below in Integration Methods.

Use your Development key first. It renders immediately with no domain restriction, so you can confirm the integration works before switching to a verified Production key.

Ad Types

Every ad request specifies a type and size. Each type only supports specific sizes:

TypeDescriptionSizes
🖼️ BannerStatic or animated image shown inlineLeaderboard (728×90), Medium Rectangle (300×250), Mobile Banner (320×50), Large Rectangle (336×280), Half Page (300×600)
🎬 VideoAuto-playing inline video, no reward gateLeaderboard (728×90), Medium Rectangle (300×250), Mobile Banner (320×50), Large Rectangle (336×280), Half Page (300×600)
🪟 InterstitialFullscreen ad shown between content transitions; close button appears after a short delayFullscreen (Interstitial / Rewarded)
🎁 RewardedFullscreen video the user opts into watching in exchange for an in-app rewardFullscreen (Interstitial / Rewarded)
  • Banner / Video render inline, at a fixed rectangle size, wherever you place the ad element.
  • Interstitial / Rewarded are always fullscreen — they render as an overlay covering the whole viewport, regardless of where the trigger element sits in your page.
  • Rewarded creatives must be a video — the viewer has to watch for a minimum time (set by the advertiser) before a reward is granted.

Integration Methods

Two ways to embed an ad slot. Both work for Banner/Video; Interstitial/Rewarded automatically render fullscreen regardless of which mode you pick.

iFrame (recommended)

Fully isolated — the ad runs in its own document, nothing it does can interfere with your page. No script tag needed.

HTML
<iframe
  src="https://amanahads.com/api/ads/frame?key=YOUR_KEY&type=BANNER&size=LEADERBOARD"
  width="728"
  height="90"
  frameborder="0"
  scrolling="no"
  style="border:none;display:block;">
</iframe>

Div / Script

Add the loader script once per page, then drop a <div> wherever you want an ad. Lightweight, renders directly in your page's DOM.

HTML
<script src="https://amanahads.com/api/ads/serve.js" data-key="YOUR_KEY" async></script>

<div
  id="amanah-ad-banner-leaderboard"
  data-type="BANNER"
  data-size="LEADERBOARD">
</div>

Add data-mode="iframe" on the div to have the script embed via iframe instead of building DOM directly — same isolation benefit as the iframe method above, without hand-writing the iframe tag.

Rewarded Ads

Rewarded ads work like AdMob or Unity Ads: AmanahAds only verifies that the viewer watched for the required time and tells your app — it never decides or grants the actual reward. What the reward is (coins, an unlocked level, extra time, an access pass, anything) is entirely up to your own app's logic.

HTML
<script src="https://amanahads.com/api/ads/serve.js" data-key="YOUR_KEY" async></script>

<div
  id="amanah-ad-rewarded"
  data-type="REWARDED"
  data-size="FULLSCREEN"
  data-onreward="onAmanahReward">
</div>

<script>
  function onAmanahReward() {
    // Called only after the server verifies the required watch time elapsed.
    // Grant your own in-app reward here — coins, unlock, whatever you want.
  }
</script>

If you're embedding via a raw iframe instead of the script loader, listen for the postMessage event instead:

HTML
<script>
  window.addEventListener("message", function (e) {
    if (e.data && e.data.type === "amanah-reward-granted") {
      onAmanahReward();
    }
  });
</script>

The watch-time check happens server-side, against the actual elapsed time since the ad was served — never trusting anything the browser reports — so it can't be gamed by calling the callback early.

Instance Setup

When you register an instance you choose one of two types:

  • Website — give the site URL. It's used to verify that ad requests on your Production key actually come from your registered domain.
  • App — give the platform (Android/iOS) and package name / bundle ID (e.g. com.example.myapp), plus an optional Play Store / App Store link.

You can also optionally declare a category and primary audience languagefor your instance — this is what lets category-targeted campaigns match your traffic (see Audience Targeting).

Ad types can be added or removed after creation too — use the Ad Types button on the instance card in your dashboard.

API Keys & Verification

Every instance gets two keys:

  • Development key — works from anywhere, auto-verified immediately. Use it for local testing, staging, or any environment that isn't your live domain yet.
  • Production key — only serves ads once an admin verifies it, and only from your registered domain/origin. This is the anti-fraud check: requests must carry an Origin/Referer matching the instance's URL.

Keys can be regenerated any time from the instance's Keys dialog if one is ever compromised.

Audience Targeting

Advertisers can optionally restrict a campaign to a specific audience. As a publisher you don't configure any of this yourself — it's automatic based on the request, except for two fields you can optionally opt into passing.

DimensionHow it's known
CountryDetected automatically from the request's IP.
Device / OSDetected automatically from the browser's User-Agent.
LanguageDetected automatically from the browser's Accept-Language header.
CategoryMatched against your instance's declared category (set once when registering, see Instance Setup).
Age / GenderNever inferred. Only used if your app explicitly passes it — add data-age / data-gender on the ad element if your own app already knows this about the viewer (e.g. from your own login).

Soft targeting: if a signal is unknown for a given request, the campaign still serves — targeting only narrows delivery where the signal actually is available. It never results in a blank ad slot just because a signal wasn't present.

API Reference

All endpoints are under https://amanahads.com/api/ads/, CORS-enabled for use from any origin.

GET /serve

Params: key, type, size (+ optional age, gender). Returns JSON.

{ "ad": { "id", "creativeUrl", "creativeType", "clickUrl", "adType", "adSize", "instanceId", "destinationUrl" } }
// or { "ad": null } when nothing is eligible to fill the slot
// or { "error": "..." } — see status codes below

GET /frame

Same params as /serve, but returns a complete standalone HTML page (for use in an iframe) with click tracking, the feedback menu, and reward/interstitial behavior already wired in.

GET /serve.js

No params — returns the embeddable loader script described in Integration Methods.

GET /click

Params: campaignId, instanceId, creativeId, key. Always redirects to the campaign's destination URL; records the click and CPC earning behind the scenes. You won't call this directly — it's the URL baked into clickUrl.

POST /reward

Body: { impressionId }. Used internally by the reward flow — see Rewarded Ads.

{ "granted": true }
// or { "granted": false, "reason": "too_early" | "not_found" | "not_a_rewarded_campaign" | "missing_impression_id" }

Error statuses (/serve and /frame)

ErrorStatusMeaning
invalid_key401The key doesn't exist or is deactivated.
instance_inactive403The instance was banned or restricted by an admin.
not_verified403Production key pending admin verification.
domain_not_approved403Request origin doesn't match the instance's registered URL.
unsupported_ad_type400This instance never registered that type/size combo.

Campaign Lifecycle

Useful context for why a slot might show nothing even when everything on your end is set up correctly — a campaign only serves once it reaches ACTIVE:

DRAFT → PENDING_REVIEW → APPROVED → PENDING_PAYMENT → ACTIVE → (PAUSED / COMPLETED / REJECTED)

A campaign leaves ACTIVE automatically once its budget is exhausted (→ COMPLETED) or its end date passes.

Earnings & Payouts

  • You earn a share of what the advertiser pays per impression, click, or granted reward — the platform commission is set globally, so your share is whatever remains after that.
  • Each earning is held briefly after being recorded (a few days) before becoming part of your withdrawable balance — this exists to absorb refunds/fraud reversals.
  • Once released, request a cashout to bKash from your dashboard, subject to a minimum cashout amount and one pending request at a time.

Bangladesh only for now: both advertiser payments and developer cashouts go exclusively through bKash. There's no card, PayPal, or other international payment method yet, so using AmanahAds in either direction currently requires a Bangladeshi bKash account.

Troubleshooting

I embedded the code but see "No ads available"

This means the request reached us fine, but no active campaign currently matches that exact ad type + size. It's usually not a setup mistake — check whether any advertiser currently has a live, funded campaign for that specific combination. Try a different registered ad type/size to confirm the pipeline itself works.

I see "Ad type not supported"

Your instance hasn't registered that exact type+size combo. Add it from the instance's Ad Types dialog.

I see "Production Key Not Verified"

Production keys need one-time admin approval before they'll serve ads. Use your Development key while waiting, or while testing anywhere other than your live domain.

I see "Unauthorized Environment"

Your Production key is verified, but the request's origin doesn't match the URL you registered for the instance. This check doesn't apply to the Development key.

The ad renders blank with nothing in it

Automated/bot traffic (headless browsers, crawlers, common scraping tools) is intentionally served an empty response rather than a real ad or an error, so this is often expected behavior for non-human requests.