How to Configure Postbacks #
Monetag’s server-side postback system allows you to receive HTTP notifications when an ad event — such as an impression or a click — is confirmed and processed by our backend.
This mechanism is essential for apps that offer user rewards, perform custom analytics, or rely on server-side validation of ad interactions.
⚠️ Postbacks are sent for these formats:
- ✅ Rewarded Interstitial (
impressionandclick)- ✅ Rewarded Popup (
impression;clickcan come from a zone linked to the popup zone)- ✅ In-App Interstitial (
impressiononly)
Step 1: Prepare Your App #
Before configuring postbacks, make sure that:
- Your Telegram Mini App (TMA) is added to your Monetag account.
- The SDK is properly integrated and activated for that app.
- You have the main SDK zone ID from your Monetag dashboard.
- Your app passes a
ymidthat is unique for each ad show, for exampleshow_XXX({ ymid: 'user-123_ad_5', requestVar: 'bonus-button' }). If you preload the ad, pass the sameymidto thepreloadcall and to the call that shows it. See{ymid}in the Macro Reference.
Step 2: Configure Postback URL in SSP #
Postbacks can now be configured directly in the Monetag SSP:

- Go to your main SDK zone settings
- Find the Postback URL field
- Paste your endpoint URL with macros (see below)
- Save the changes

Each SDK can have its own postback configuration.
If your Mini App uses multiple ad formats (e.g. Interstitial + Popup), the {sub_zone_id} macro will help you distinguish which zone triggered the postback.
Step 3: Prepare Your Postback URL #
Monetag will send a GET request to your endpoint for each confirmed monetized ad event.
You can use macros in your URL — these will be replaced with event-specific values by Monetag.
Example:
https://yourdomain.com/postback?secret=YOUR_SECRET&ymid={ymid}&zone_id={zone_id}&event_type={event_type}&reward_event_type={reward_event_type}&estimated_price={estimated_price}
Replace YOUR_SECRET with a long random string of letters and digits. The URL is stored in Monetag and never reaches the app, so a request without this value did not come from Monetag. Your endpoint rejects such requests, see Step 4.
📖 See the Macro Reference section for a full list of available placeholders.
Step 4: Implement the Endpoint #
Your backend must accept GET requests and parse the query parameters.
The examples grant one reward per ymid. This works only if you pass a unique ymid for each ad show, for example user-123_ad_5, not just a user ID.
Node.js (Express):
app.get('/postback', (req, res) => {
const { secret, ymid, event_type, reward_event_type, zone_id } = req.query
// reject requests without the secret from your postback URL: they did not come from Monetag
if (!secret || secret !== process.env.POSTBACK_SECRET) {
return res.sendStatus(403)
}
console.log(`[Postback] ymid=${ymid}, event_type=${event_type}, reward_event_type=${reward_event_type}, zone_id=${zone_id}`)
// one reward per ymid: retries and the impression and click of one ad show repeat it
if (reward_event_type === 'valued') {
rewardUserOnce(ymid)
}
res.sendStatus(200)
})
PHP:
<?php
// reject requests without the secret from your postback URL: they did not come from Monetag
$secret = $_GET['secret'] ?? '';
if ($secret === '' || $secret !== getenv('POSTBACK_SECRET')) {
http_response_code(403);
exit;
}
$ymid = $_GET['ymid'] ?? null;
$rewardEventType = $_GET['reward_event_type'] ?? null;
// one reward per ymid: retries and the impression and click of one ad show repeat it
if ($rewardEventType === 'valued') {
reward_user_once($ymid);
}
http_response_code(200);
Python (Flask):
import os
from flask import Flask, request
app = Flask(__name__)
@app.route("/postback")
def postback():
# reject requests without the secret from your postback URL: they did not come from Monetag
secret = request.args.get("secret")
if not secret or secret != os.environ.get("POSTBACK_SECRET"):
return "", 403
ymid = request.args.get("ymid")
event = request.args.get("event_type")
reward_event_type = request.args.get("reward_event_type")
print(f"[Postback] ymid={ymid}, event_type={event}, reward_event_type={reward_event_type}")
# one reward per ymid: retries and the impression and click of one ad show repeat it
if reward_event_type == "valued":
reward_user_once(ymid)
return "", 200
We recommend:
- Logging all postbacks
- Ensuring idempotency via ymid
- Always returning 200 OK for successful processing
Step 5: Understand Retry Behavior #
A 2xx response counts as delivered. Redirects are not followed, so a 3xx response counts as a failure.
- If your server answers with a status of 300 or higher or does not answer within 30 seconds, Monetag retries the postback after 1, 5, 15, 30, 60, 90, 120 and 180 minutes, then after 30 hours. Each wait counts from the previous attempt.
- After a connection error (connection refused, DNS failure), Monetag retries once, after 30 hours.
- After the last retry the postback is dropped.
- Monetag does not deduplicate postbacks. The same postback can arrive more than once.
- Make sure your endpoint is available and efficient
Best Practices #
To ensure correct and secure processing:
- ✅ Always use a unique ymid per ad show
- ✅ Validate all parameters to prevent abuse or broken logic
- ✅ Use HTTPS and avoid redirects
- ✅ Log all postbacks for monitoring and debugging
- ✅ Ensure idempotency by using ymid to avoid duplicate rewards
- ✅ Add a secret parameter to your postback URL, for example
&secret=<random string>, and reject requests without it. The URL is stored in Monetag and never reaches the app - ✅ Call the SDK with your main zone ID only. The zone that delivered the ad arrives in
{sub_zone_id} - ✅ Use
request_varto see where in your UI the ad was shown
Once your setup is complete, test postbacks by triggering real ad views in your app.