This guide covers installation, initialization, ad formats, privacy, testing, and mediated networks. The complete Lua API is documented in the API reference.
If you are upgrading from 1.x, start with the migration guide.
| Component | Minimum |
|---|---|
| Defold | 1.13.0 |
| Android | API 24 |
| iOS | iOS 15 |
| AppLovin MAX | 13.6.3 |
Open game.project in the Defold editor and select Project in the left
sidebar. Under Dependencies, click + and paste:
https://github.com/defold/extension-applovin/archive/refs/tags/2.0.0.zip
Then select Project > Fetch Libraries from the main menu.
In the game.project editor, also configure:
24Register your Android package and iOS bundle identifier in MAX. Use the SDK key from Account > General > Keys, and create separate ad units for each platform and format.
The extension is not available on desktop or HTML5. Guard shared code:
if applovin then
-- Android or iOS
end
MAX initializes asynchronously:
initialize() once.OnSdkInitializedEvent.local interstitial_id = "YOUR_INTERSTITIAL_AD_UNIT_ID"
local function max_callback(self, event, data)
if event == "OnSdkInitializedEvent" then
applovin.load_interstitial(interstitial_id)
elseif event == "OnInterstitialAdLoadFailedEvent" then
print("MAX load failed", data.code, data.message)
elseif event == "OnInterstitialAdRevenuePaidEvent" then
print("MAX revenue", data.revenue, data.revenuePrecision)
end
end
function init(self)
applovin.set_callback(max_callback)
-- Values supplied by your consent UI or CMP:
applovin.set_has_user_consent(user_has_consented)
applovin.set_do_not_sell(user_opted_out)
applovin.initialize("YOUR_APPLOVIN_SDK_KEY")
end
function final(self)
applovin.set_callback(nil)
end
is_initialized() becomes true after initialization completes. Handle
OnSdkInitializedEvent when loading the first ads instead of polling it.
Your application is responsible for choosing the correct disclosures and
consent flow. Apply set_has_user_consent() and set_do_not_sell() before
initialization and persist the user’s choice in your own system. Their getters
return booleans and cannot distinguish “unset” from false.
Follow AppLovin’s current privacy guide. Do not initialize AppLovin for users or apps prohibited by that policy.
The MAX Terms and Privacy Policy Flow is optional. Before enabling it:
Configure the flow before initialization:
applovin.set_terms_and_privacy_policy_flow_enabled(true)
applovin.set_privacy_policy_url("https://example.com/privacy")
applovin.set_terms_of_service_url("https://example.com/terms") -- optional
applovin.initialize("YOUR_APPLOVIN_SDK_KEY")
Android builds include Google UMP 4.0.0. If another extension also declares UMP, do not force an older version. On iOS, enable the appropriate Google adapter and app ID when required by your consent setup.
After initialization, has_supported_cmp() tells you whether
show_cmp_for_existing_user() can present a Manage privacy settings
screen. Completion is reported through OnCmpCompletedEvent.
Review the final application—not only the base extension—for permissions, privacy declarations, and mediated SDK data collection:
The extension includes AppLovin’s current list automatically. Enabling an iOS adapter also includes that network’s current identifiers. App-specific entries from another manifest are merged with these lists.
Set test-device IDs before initialization:
applovin.set_test_device_advertising_ids({
"YOUR_IDFA_OR_GAID",
})
Use only identifiers from your QA devices and remove them from production configuration.
After initialization, call show_mediation_debugger() from a visible QA
button. Use it to verify the SDK key, adapters, privacy state, test mode, CMP,
and ad units. Enable verbose logging and the Creative Debugger only in
development builds.
All ad calls require an ad-unit ID for the current package or bundle identifier.
applovin.load_interstitial(ad_unit_id)
-- After OnInterstitialAdLoadedEvent:
if applovin.is_interstitial_ready(ad_unit_id) then
applovin.show_interstitial(ad_unit_id, "level_complete")
end
Load the next ad after the previous one is hidden or fails.
applovin.load_rewarded_ad(ad_unit_id)
-- After OnRewardedAdLoadedEvent:
if applovin.is_rewarded_ad_ready(ad_unit_id) then
applovin.show_rewarded_ad(ad_unit_id, "daily_reward")
end
Grant rewards only from OnRewardedAdReceivedRewardEvent, using its label
and amount.
applovin.set_banner_placement(ad_unit_id, "main_menu")
applovin.create_banner(ad_unit_id, "bottom_center")
applovin.set_banner_background_color(ad_unit_id, "#000000")
applovin.hide_banner(ad_unit_id)
applovin.show_banner(ad_unit_id)
applovin.update_banner_position(ad_unit_id, "top_center")
applovin.stop_banner_auto_refresh(ad_unit_id)
applovin.start_banner_auto_refresh(ad_unit_id)
applovin.destroy_banner(ad_unit_id)
Set placement before creation so it is included in the first load. Destroy the view when its screen no longer needs it.
applovin.set_mrec_placement(ad_unit_id, "store")
applovin.create_mrec(ad_unit_id, "centered")
applovin.hide_mrec(ad_unit_id)
applovin.show_mrec(ad_unit_id)
applovin.update_mrec_position(ad_unit_id, "bottom_center")
applovin.stop_mrec_auto_refresh(ad_unit_id)
applovin.start_mrec_auto_refresh(ad_unit_id)
applovin.destroy_mrec(ad_unit_id)
MREC event names use MRec, including OnMRecAdExpandedEvent.
Each format has its own extra-parameter function:
applovin.set_interstitial_extra_parameter(ad_unit_id, key, value)
applovin.set_rewarded_ad_extra_parameter(ad_unit_id, key, value)
applovin.set_banner_extra_parameter(ad_unit_id, key, value)
applovin.set_mrec_extra_parameter(ad_unit_id, key, value)
Only use keys documented by AppLovin or the mediated network.
The callback signature is:
function(self, event_name, params)
Callbacks run from the Defold update thread. Keep them short. The complete event and constant list is in the API reference.
Ad payloads can include:
adUnitIdentifier, format, placementnetworkName, networkPlacement, creativeIdentifierrevenue, revenuePrecisionrequestLatencyMillisdspName, dspIdentifierSome mediated networks omit fields they cannot provide. Load failures contain
code, message, and request latency. Display failures can also contain
mediatedNetworkErrorCode and mediatedNetworkErrorMessage. See the official
error reference.
The base extension includes MAX but no optional third-party adapters. Enable only the networks used by your MAX account:
[applovin]
meta_android = 1
meta_ios = 1
Android and iOS switches are independent. Available property names and pinned
versions are listed in
updater/adapters.json.
Google also requires an application ID:
[applovin]
google_android = 1
google_android_app_id = ca-app-pub-0000000000000000~0000000000
google_ios = 1
google_ios_app_id = ca-app-pub-0000000000000000~0000000000
Follow the official mediated-network guide for account setup, permissions, manifests, privacy disclosures, and any extra initialization. Re-run the Mediation Debugger after changing adapters.
track_event() takes a non-empty event name and a JSON object:
applovin.track_event("level_complete", json.encode({
level = 12,
difficulty = "hard",
}))
Invalid JSON is logged and sent as an empty parameter map.
The repository example includes a demo SDK key:
applovin.demo_sdk_key in the bundled
game.projectc.is_*_ready()
immediately before showing.For repository builds and releases, see DEVELOPMENT.md.