Skip to content

AppLovin MAX

  1. In MAX, Account → General → Keys, copy the Event Key and store it:
Terminal window
npx @kasskeep/cli ads credentials --id app_xxx --applovin-event-key-file - < ./max-event-key.txt

Without it callbacks return 422 applovin_not_configured.

  1. In Ad Units, edit the rewarded ad unit and set Server Side Callback URL. Keep the macro names exactly as written:
https://api.kasskeep.com/v1/ads/applovin/<app_id>/s2s?event_id={EVENT_ID}&event_token={EVENT_TOKEN}&user_id={USER_ID}&ad_unit_id={AD_UNIT_ID}&amount={AMOUNT}&currency={CURRENCY}&custom_data={CUSTOM_DATA}&ts={TS}&platform={PLATFORM}&placement={PLACEMENT}&network_name={NETWORK_NAME}

GET .../apps/:app_id/ad-networks returns this string as callback_path.

  1. Map the ad unit: ads unit-set --id app_xxx --name revive --applovin a1b2c3d4e5f60718.
  2. On the client call AppLovinMAX.setUserId(appUserId) and pass customData as the third argument of RewardedAd.showAd. Kasskeep.ads.showRewarded does both through your provider.

{EVENT_TOKEN} must equal the hex sha1(EVENT_ID + Event Key), compared in constant time; otherwise 400 invalid_signature. The token covers only the event id, but each event id is recorded once, so replaying a callback with a different user_id cannot earn a second reward.

MAX parameter Event field
user_id app_user_id
ad_unit_id network_ad_unit_id, mapped to ad_unit
amount reward_amount
currency reward_type
event_id network_transaction_id
custom_data custom_data
ts occurred_at
platform top-level platform

MAX sends S2S callbacks only for live ads, not for test ads. Use test mode during development.

import AppLovinMAX, { RewardedAd } from "react-native-applovin-max";
import type { RewardedProvider } from "@kasskeep/react-native";
export const maxRewarded: RewardedProvider = {
network: "applovin",
setUserId: (appUserId) => AppLovinMAX.setUserId(appUserId),
showRewarded: ({ networkAdUnitId, customData }) =>
new Promise((resolve) => {
let rewarded = false;
const done = (status: "completed" | "skipped" | "failed") => {
RewardedAd.removeAdReceivedRewardEventListener();
RewardedAd.removeAdHiddenEventListener();
RewardedAd.removeAdDisplayFailedEventListener();
resolve({ status });
};
RewardedAd.addAdReceivedRewardEventListener(() => (rewarded = true));
RewardedAd.addAdHiddenEventListener(() => done(rewarded ? "completed" : "skipped"));
RewardedAd.addAdDisplayFailedEventListener(() => done("failed"));
RewardedAd.showAd(networkAdUnitId, undefined, customData);
}),
};

Load the ad with RewardedAd.loadAd before showing it.