Moments
Mobile
Flutter Integration Guide
26min
overview this guide explains how to integrate the momentscience sdk into your flutter application the sdk supports two integration modes, both designed to prefetch offers and present them at checkout using a webview integration modes sdk prefetch mode in this mode, the sdk automatically prefetches and caches offers using a 0Γ0 webview in the background when the user reaches the checkout step, cached offers are displayed instantly simplest integration path no need to make manual api calls api prefetch mode in this mode, the app fetches offers using a native https call and passes the response to the sdk at checkout full control over when and how offers are requested ability to customize the request payload (e g , user id, cart value) in both modes, offers are rendered in a webview at the checkout screen because offers are preloaded before checkout, the user experience remains fast and frictionless, even when no offers are found if no offers are returned, you can choose to skip showing the offer display screen altogether requirements to integrate the momentscience sdk into your flutter app, ensure the following prerequisites are met a valid momentscience sdk id learn more about getting your sdk id https //docs momentscience com/getting your sdk id environment flutter 3 29 2+ dart 3 7 2+ ios minimum deployment target ios 12 android minimum sdk version api level 19 setup instructions step 1 add dependencies add html assets add the required html templates to your project these files are used by the sdk to render the offer experience in a webview place the following files in the assets/html/ directory checkout html https //github com/adspostx/examples/blob/main/flutter/momentsciencesdkdemoapp flutter/mssdk demo app/assets/html/checkout html prefetch html https //github com/adspostx/examples/blob/main/flutter/momentsciencesdkdemoapp flutter/mssdk demo app/assets/html/prefetch html declare the asset path in your pubspec yaml file flutter assets \ assets/html/ add and install dependencies update your pubspec yaml file with the required packages dependencies http ^1 1 0 # for making api requests device info plus ^9 1 0 # for retrieving user agent information flutter inappwebview ^6 1 5 # for rendering the offers in webview url launcher ^6 1 10 # for launching urls externally flutter dotenv ^5 0 2 # for managing environment variables after adding the dependencies, install them by running the following command from your project root flutter pub get add internet permission to enable internet access for offer delivery, add the following permission to your android manifest file (android/app/src/main/androidmanifest xml) insert it inside \<manifest> but before \<application> \<uses permission android\ name="android permission internet" /> this is required for the sdk to load offer content in both integration modes step 2 prefetch offers (sdk or api) you can prefetch offers using one of two modes sdk prefetch uses a hidden 0Γ0 webview to preload offers api prefetch uses a native api call to fetch offers, which are then injected into the sdk display template in both modes, you can skip showing the checkout screen if no offers are found option 1 sdk prefetch this approach uses a 0Γ0 webview to preload the sdk when offers are found, the sdk sends an ads found event to your app itβs the lightest touch integration, ideal when you want minimal native logic step 1 load the web sdk in a 0Γ0 webview to prefetch offers place a small, hidden webview on a screen before checkout make sure to enable java script, dom storage, database for webview example offers screen dart register a javascript interface to listen for sdk events inappwebview( onwebviewcreated (controller) { webviewcontroller = controller; controller addjavascripthandler( handlername 'adpxcallback', callback (args) { if (args length >= 2) { string event = args\[0]; string payload = args\[1]; prefetchservice handlewebsdkevent(event, payload); } return null; }, ); }, ) the web sdk uses this interface to notify your app when key events occur for example, the ads found event indicates that offers are available, allowing your app to conditionally show or skip the checkout screen 3\ load the webview using a pre filled html template use a local html template to inject your sdk id and payload values, then load the final html into the hidden webview πexample prefetch service dart // pass the webview controller to prefetchwithwebsdk await prefetchservice prefetchwithwebsdk( sdkidcontroller text trim(), webviewcontroller); avoid using about\ blank as the base url, it will cause a security error prefetchwithwebsdk() replaces placeholders in prefetch template html with real values sdkid , payload , and adpxuser which loads the sdk in prefetch mode payload example you can create payload with key value pair of map\<string, string> type, eg like below see createpayload() method map\<string, string> createpayload() { return { 'pub user id' getuniqueid(), 'placement' 'checkout', 'themeid' 'standered theme', }; } once ads found is received, check the offercount if it's 0 , you can skip rendering the checkout screen entirely example prefetch service dart step 2 show offers using fullscreen webview after confirming that offers are available, render the offers on your checkout screen using a full screen webview, pass required parameters as below navigator push( context, materialpageroute( builder (context) => checkoutscreen( sdkid sdkidcontroller text trim(), prefetchmethod prefetchmethod, apiresponse apiresponse, // only needed for api prefetch offercount offercount, payload payload, ), ), ) 2\ the full screen webview loads the offer experience using the checkoutview\ html template this html file dynamically injects your configuration and prefetch result make sure to enable java script, dom storage and database for webview try { await checkoutservice loadcontentintowebview( controller controller, sdkid widget sdkid, isprefetchapi widget prefetchmethod == prefetchmethod api, apiresponse widget apiresponse, offercount widget offercount, payload widget payload, ); } catch (e) { // handle error here } } } example checkout service dart option 2 prefetch with api in this method, your app fetches offers from the momentscience offers api ahead of time and passes them into the web sdk at render time step 1 fetch offers via momentscience offers api start by making a post request to the offers endpoint post https //api adspostx com/native/v4/offers json save the api response locally so it can be used later when displaying offers for implementation details, see network service dart https //github com/adspostx/examples/blob/main/flutter/momentsciencesdkdemoapp flutter/mssdk demo app/lib/services/network service dart await prefetchservice prefetchwithapi( sdkidcontroller text trim()); // extract the offer count from the api response int offercount = prefetchservice getoffercount(); hereβs a simplified version of how the prefetchwithapi method works under the hood future\<void> prefetchwithapi(string sdkid) async { try { final useragent = await deviceutils getuseragent(); final payload = createpayload(); lastusedpayload = payload; debugprint('prefetching content with api for sdk id $sdkid'); debugprint('user agent $useragent'); final response = await networkservice fetchoffers( sdkid sdkid, ua useragent, dev '1', // use '1' for enabling test mode payload payload, ); cachedapiresponse = response; debugprint('api prefetch successful'); debugprint( 'response ${response tostring() substring(0, response tostring() length > 100 ? 100 response tostring() length)} ', ); } catch (e) { debugprint('error during api prefetch $e'); rethrow; } } step 2 show offers in fullscreen webview once youβve confirmed offer availability from the api response use a full screen webview to display the offer experience using the moments web sdk ,navigate to the checkout screen, and pass the required values navigator push( context, materialpageroute( builder (context) => checkoutscreen( sdkid sdkidcontroller text trim(), prefetchmethod prefetchmethod, apiresponse apiresponse, offercount offercount, payload payload, ), ), ) display the checkout screen with webview future\<void> loadcontent(inappwebviewcontroller controller) async { try { await checkoutservice loadcontentintowebview( controller controller, sdkid widget sdkid, isprefetchapi widget prefetchmethod == prefetchmethod api, apiresponse widget apiresponse, offercount widget offercount, payload widget payload, ); } catch (e) { debugprint('error loading content $e'); setstate(() { iswebviewloading = false; }); } } checkoutservice loadcontentintowebview loads html from prefilled checkout html π example checkout screen dart https //github com/adspostx/examples/blob/main/flutter/momentsciencesdkdemoapp flutter/mssdk demo app/lib/screens/checkout screen dart checkoutview\ html https //github com/adspostx/examples/blob/main/flutter/momentsciencesdkdemoapp flutter/mssdk demo app/assets/html/checkout html checkout service dart https //github com/adspostx/examples/blob/main/flutter/momentsciencesdkdemoapp flutter/mssdk demo app/lib/services/checkout service dart step 3 open clicks in an external browser to ensure that offer clickouts open in the system browser (not inside the webview), capture javascript callback events and manually launch external urls implementation steps set up a javascript handler in the webview to listen for offer click events example checkout screen dart controller addjavascripthandler( handlername 'adpxcallback', callback (args) { if (args length >= 2) { string event = args\[0]; dynamic payload = args\[1]; debugprint('webview callback $event, $payload'); checkoutservice handleadevent(event, payload); } return null; }, ); handle the url clicked event and open the target url externally example checkout service dart future\<void> handleadevent(string event, dynamic payload) async { debugprint('processing ad event $event'); if (event == 'url clicked') { await processurlevent(payload); } } future\<void> processurlevent(dynamic payload) async { try { map\<string, dynamic> payloadmap; if (payload is string) { try { payloadmap = map\<string, dynamic> from(json decode(payload)); } catch (e) { debugprint('error parsing payload $e'); return; } } else if (payload is map) { payloadmap = map\<string, dynamic> from(payload); } else { debugprint('unexpected payload type ${payload runtimetype}'); return; } if (payloadmap containskey('target url')) { final targeturl = payloadmap\['target url']; if (targeturl != null && targeturl is string) { final normalizedurl = normalizeurl(targeturl); externallyopenedurls add(normalizedurl); await openexternalurl(normalizedurl); } } } catch (e) { debugprint('error processing url event $e'); } } since youβre opening urls manually via callback, block duplicate navigation inside the webview future\<navigationactionpolicy> handleurlnavigation(navigationaction navigationaction) async { final uri = navigationaction request url; if (uri != null) { await future delayed(const duration(seconds 1)); final url = uri tostring(); final normalizedurl = normalizeurl(url); debugprint('intercepted url $normalizedurl'); if ( externallyopenedurls contains(normalizedurl)) { debugprint('canceling navigation for externally opened url $normalizedurl'); return navigationactionpolicy cancel; } return navigationactionpolicy allow; } return navigationactionpolicy cancel; } check out the momentscience flutter demo on github to see the complete implementation, including offer fetching, webview rendering, event handling, and external link support conclusion congratulations! you've successfully integrated the momentscience sdk into your flutter app, whether youβre using sdk prefetch mode or api prefetch mode, your app is now equipped to deliver personalized offers directly within the user experience this setup enables dynamic monetization while preserving control over when and how offers are displayed π’ if you're running into any issues while going through the integration process, feel free to contact us at help\@m omentscience com