Solutions
...
Serving MomentPerks in Mobile ...
Flutter - Moments API Integration Guide
overview the https //docs momentscience com/momentperks api allows you to display personalized offers to users inside your flutter application this guide explains how to integrate the api, from setup to rendering offers and tracking user actions by following this integration guide, youβll be able to fetch real time, targeted offers based on user context present these offers using your own custom ui or prebuilt reference components track user responses and impressions for reporting and optimization to explore a working example, see the https //github com/adspostx/examples/tree/main/flutter/momentsapidemoapp flutter prerequisites before you begin, ensure the following requirements are met api key before you start the integration, you must acquire a unique api key follow the https //docs momentscience com/getting your api key to obtain your key install dependency packages add the following dependencies to your pubspec yaml file pubspec yaml dependencies http ^1 4 0 # api requests url launcher ^6 3 1 # open links in an external browser tinycolor2 ^3 0 1 # convert and manage hex color values provider ^6 0 5 # optional for better state management enable internet access add the following permission to your android appβs manifest android/app/src/main/androidmanifest xml androidmanifest xml \<uses permission android\ name="android permission internet" /> integration steps the moments api delivers personalized offer data based on a set of query parameters and request payload values in this section, youβll implement a utility function to retrieve and normalize offers for use in your ui for complete details on moments api, refer to the https //docs momentscience com/momentperks api step 1 fetch offers in this step, youβll build a utility function that sends a post request to the https //docs momentscience com/momentperks api ( native/v4/offers json ) and returns personalized offers based on the given user context instructions define base url and endpoint at the top of offer service dart , define the api constants const string baseurl = 'https //api adspostx com/native/v4'; const string path = 'offers json'; implement loadoffers function paste the following function loadoffers function import 'dart\ convert'; import 'package\ http/http dart' as http; import ' /utils/user agent util dart'; future\<offerresponse> loadoffers({ required string apikey, string? loyaltyboost, string? creative, string? campaignid, bool isdevelopment = false, map\<string, string> payload = const {}, }) async { if (apikey isempty) { throw exception('api key cannot be empty'); } // validate loyaltyboost if provided if (loyaltyboost != null) { final validloyaltyboostvalues = \['0', '1', '2']; if (!validloyaltyboostvalues contains(loyaltyboost)) { throw exception('loyaltyboost must be one of these values 0, 1, or 2'); } } // validate creative if provided if (creative != null) { final validcreativevalues = \['0', '1']; if (!validcreativevalues contains(creative)) { throw exception('creative must be either 0 or 1'); } } // construct the uri with query parameters final queryparams = {'api key' apikey}; // add optional parameters only if they are provided if (loyaltyboost != null) { queryparams\['loyaltyboost'] = loyaltyboost; } if (creative != null) { queryparams\['creative'] = creative; } if (campaignid != null) { queryparams\['campaignid'] = campaignid; } final uri uri = uri parse('$ baseurl/$ path') replace(queryparameters queryparams); // prepare the payload, adding the development flag if needed final map\<string, string> updatedpayload = map from(payload); if (isdevelopment) { updatedpayload\['dev'] = '1'; } try { // prepare headers with user agent final headers = { 'content type' 'application/json', 'accept' 'application/json', 'user agent' payload\['ua'] ?? useragentutil getuseragent(), }; // make the post request to the offers api with timeout final response = await http post(uri, headers headers, body jsonencode(updatedpayload)) timeout(const duration(seconds 30)); // if the response is successful, decode and return as typed model if (response statuscode == 200) { final jsondata = jsondecode(response body) as map\<string, dynamic>; return offerresponse fromjson(jsondata); } else { // throw an exception for non 200 responses throw exception('api error ${response statuscode} ${response body}'); } } on timeoutexception { // handle timeout specifically throw exception('request timed out please check your connection and try again '); } catch (e) { // catch and rethrow any errors during the request throw exception('error making api call $e'); } } use the function in your app call the loadoffers() function anywhere in your app where you need to fetch offers for example loadoffers usage final offers = await loadoffers( apikey 'your api key', payload { 'adpx fp' 'unique device fp', 'pub user id' 'user123', 'placement' 'checkout success', }, loyaltyboost '0', creative '0', isdevelopment true, // do not use 'true' in prod code ); notes on parameters true 330,331 unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type common payload fields true 220,220,221 unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type see https //github com/adspostx/examples/blob/main/flutter/momentsapidemoapp flutter/msapidemoapp fl/lib/service/offer service dart and https //github com/adspostx/examples/blob/main/flutter/momentsapidemoapp flutter/msapidemoapp fl/lib/utils/user agent util dart in the demo app for a working implementation step 2 build the offer ui after retrieving offer data, you need to design a user interface to present the offers and handle user actions such as claiming or dismissing them the ui example provided below uses offercontainerview https //github com/adspostx/examples/blob/main/flutter/momentsapidemoapp flutter/msapidemoapp fl/lib/components/offer container view\ dart offerview https //github com/adspostx/examples/blob/main/flutter/momentsapidemoapp flutter/msapidemoapp fl/lib/components/offer view\ dart offer viewmodel dart https //github com/adspostx/examples/blob/main/flutter/momentsapidemoapp flutter/msapidemoapp fl/lib/viewmodels/offer viewmodel dart from our demo app these are reference implementations only, you are free to implement your own ui components based on your app's design requirements and platform conventions for a detailed explanation of how each field in the offer object is used refer to the https //docs momentscience com/offer anatomy this guide will help you understand how to map api fields to ui components and apply dynamic styling correctly offer container ui the offercontainerview displays multiple offers in sequence and manages user navigation, loading, and error states offercontainerview(offers ary of offers) parameter true 220,220,221 unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type see https //github com/adspostx/examples/blob/main/flutter/momentsapidemoapp flutter/msapidemoapp fl/lib/components/offer container view\ dart and https //github com/adspostx/examples/blob/main/flutter/momentsapidemoapp flutter/msapidemoapp fl/lib/viewmodels/offer viewmodel dart in the demp app for a working implementation individual offer ui each offer is displayed using the offerview widget, which presents offer details such as title, image, description, and call to action buttons with dynamic styling the business logic and state for the offer presentation are managed by the offer viewmodel dart offerview( title currentoffer\['title'], description currentoffer\['description'], imageurl currentoffer\['image'], positivecta currentoffer\['cta yes'], negativecta currentoffer\['cta no'], onpositivepressed () { handlepositivectatap(currentoffer); }, onnegativepressed () { handlenegativectatap(currentoffer); }, // styles from api response styles apistyles, ) parameters true 220,220,221 unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type unhandled content type see https //github com/adspostx/examples/blob/main/flutter/momentsapidemoapp flutter/msapidemoapp fl/lib/components/offer view\ dart and https //github com/adspostx/examples/blob/main/flutter/momentsapidemoapp flutter/msapidemoapp fl/lib/components/offer container view\ dart in the demo app for a working implementation if you prefer to use your own layout, styling, or framework specific widgets, you can parse the offer response manually use the https //docs momentscience com/offer anatomy documentation to map fields like title, image, cta yes, etc apply any visual styling or logic defined in your own architecture this approach gives you full control over the user experience, while still integrating with the core moments api logic step 3 track user interactions to monitor engagement and ensure accurate analytics, send tracking requests when users interact with offers this includes impressions, dismissals, and cta clicks create a function to fire tracking beacons define a utility function to send tracking pixels via http get requests sendtrackingrequest future\<void> sendtrackingrequest(string url) async { if (url isnotempty) { try { await apiservice sendrequest(url); debugprint('π€ sent tracking request to $url'); } catch (e) { debugprint('error sending tracking request to $url $e'); } } } sendrequest future\<void> sendrequest(string url) async { if (url isempty) { throw exception('url cannot be empty'); } final uri uri = uri parse(url); try { // make the get request for tracking or similar purposes with timeout await http get(uri, headers {'accept' 'application/json'}) timeout(const duration(seconds 10)); // no response processing or return value needed } on timeoutexception { // handle timeout for tracking requests throw exception('tracking request timed out $url'); } catch (e) { // catch and rethrow any errors during the request throw exception('error making get request $e'); } } track when an offer is displayed when rendering an offer, send impression pixels final pixel = offer pixel; if (pixel != null && pixel isnotempty) { unawaited(sendtrackingrequest(pixel)); } final advpixelurl = offer advpixelurl; if (advpixelurl != null && advpixelurl isnotempty) { unawaited(sendtrackingrequest(advpixelurl)); } track when the offer container is closed send the "close" beacon when a user dismisses the offer container handlecloseaction future\<void> handlecloseaction(dynamic offer) async { final closebeacon = offer beacons? close; if (closebeacon != null && closebeacon isnotempty) { unawaited(sendtrackingrequest(closebeacon)); } } track when the negative cta is clicked fire the no thanks click beacon if a user taps on negative cta final nothanksbeacon = offer beacons? nothanksclick; if (nothanksbeacon != null && nothanksbeacon isnotempty) { unawaited(sendtrackingrequest(nothanksbeacon)); } see https //github com/adspostx/examples/blob/main/flutter/momentsapidemoapp flutter/msapidemoapp fl/lib/viewmodels/offer viewmodel dart in the demo app for a working implementation next steps we recommend that you go through https //docs momentscience com/momentperks integration checklist to verify your integration completing this checklist ensures that all best practices and requirements are met for a successful moments api deployment π’ if you're running into any issues while going through the integration process, feel free to contact us at mailto\ help\@momentscience com