function canLoadAd(adType, config, params, isDebug) { var debug = strToBool(isDebug); var config1 = JSON.parse(config); var rules = getAdjustedSuppressionRules(config1, debug); prettyPrint(rules, debug); var params1 = JSON.parse(params); var states = getAdjustedStatesWithDefault(params1); prettyPrint(states, debug); var results = getLoadSuppressionRulesResults(adType, rules, states); prettyPrint(results, debug); return andOperation(results); } function canShowAd(adType, config, params, isDebug) { var debug = strToBool(isDebug); var config1 = JSON.parse(config); var rules = getAdjustedSuppressionRules(config1, debug); prettyPrint(rules, debug); var params1 = JSON.parse(params); var states = getAdjustedStatesWithDefault(params1); prettyPrint(states, debug); var loadResults = getLoadSuppressionRulesResults(adType, rules, states); if (!andOperation(loadResults)) { prettyPrint(loadResults, debug); return false; } var showResults = getShowSuppressionRulesResults(adType, rules, states); prettyPrint(showResults, debug); return andOperation(showResults); } function getLoadSuppressionRulesResults(adType, rules, states) { var results = {}; if (isBanner(adType)) { return results; } if (rules.tutorialCheckEnabled) { results.tutorialCheck = states.tutorialComplete; } if (rules.elapsedTimeSinceAppInstallInSecs) { // passed less than elapsedTimeSinceAppInstallInSecs since app is installed results.newUserCheck = getTimeDifferenceInSeconds(states.currentTimeInMs, states.appInstallTimeInMs) > rules.elapsedTimeSinceAppInstallInSecs; } if (rules.minUserLtvInUsd) { // paid more than minUserLtvInUsd var recentPayerCheck = (states.userLtvInUsd * 100) >= (rules.minUserLtvInUsd * 100); if (rules.elapsedTimeSinceLastPurchaseInSecs) { // made a purchase within elapsedTimeSinceLastPurchaseInSecs recentPayerCheck = recentPayerCheck && (getTimeDifferenceInSeconds(states.currentTimeInMs, states.lastPurchaseTimeInMs) < rules.elapsedTimeSinceLastPurchaseInSecs); } results.recentPayerCheck = !recentPayerCheck; } return results; } function getShowSuppressionRulesResults(adType, rules, states) { var results = getLoadSuppressionRulesResults(adType, rules, states); if (isBanner(adType)) { if (rules.elapsedTimeSinceAppInstallInDays) { // passed less than elapsedTimeSinceAppInstallInDays since app is installed results.installedDaysAgoCheck = getTimeDifferenceInDays(states.currentTimeInMs, states.appInstallTimeInMs) > rules.elapsedTimeSinceAppInstallInDays; } if (rules.minUserLtvInUsd) { results.spenderCheck = states.userLtvInUsd < rules.minUserLtvInUsd; } } else { if (rules.elapsedTimeSinceCurrentLaunchInSecs) { results.currentSessionDurationCheck = getTimeDifferenceInSeconds(states.currentTimeInMs, states.currentLaunchTimeInMs) > rules.elapsedTimeSinceCurrentLaunchInSecs; } if (rules.elapsedTimeSinceLastAdShownInSecs) { results.nextAdShowCheck = getTimeDifferenceInSeconds(states.currentTimeInMs, states.lastAdDismissedTimeInMs) > rules.elapsedTimeSinceLastAdShownInSecs; } } return results; } function getAdjustedStatesWithDefault(states) { // provide default values for null fields states.tutorialComplete = states.tutorialComplete != null ? states.tutorialComplete : true; states.appInstallTimeInMs = states.appInstallTimeInMs != null ? states.appInstallTimeInMs : 0; states.userLtvInUsd = states.userLtvInUsd != null ? states.userLtvInUsd : 0; states.lastPurchaseTimeInMs = states.lastPurchaseTimeInMs != null ? states.lastPurchaseTimeInMs : 0; if (!isBoolean(states.tutorialComplete) || !isNumber(states.appInstallTimeInMs) || !isNumber(states.userLtvInUsd) || !isNumber(states.lastPurchaseTimeInMs)) { throw new Error("Invalid type of parameter is passed."); } return states; } function getAdjustedSuppressionRules(config, debug) { // provide default values for null fields var defaultRules = defaultSuppressionRules(); var minUserLtvInUsd = config.minUserLtvInUsd != null ? config.minUserLtvInUsd : defaultRules.minUserLtvInUsd; var elapsedTimeSinceCurrentLaunchInSecs = config.elapsedTimeSinceCurrentLaunchInSecs != null ? config.elapsedTimeSinceCurrentLaunchInSecs : defaultRules.elapsedTimeSinceCurrentLaunchInSecs; var elapsedTimeSinceAppInstallInSecs = config.elapsedTimeSinceAppInstallInSecs != null ? config.elapsedTimeSinceAppInstallInSecs : defaultRules.elapsedTimeSinceAppInstallInSecs; var elapsedTimeSinceAppInstallInDays = config.elapsedTimeSinceAppInstallInDays != null ? config.elapsedTimeSinceAppInstallInDays : defaultRules.elapsedTimeSinceAppInstallInDays; var elapsedTimeSinceLastAdShownInSecs = config.elapsedTimeSinceLastAdShownInSecs != null ? config.elapsedTimeSinceLastAdShownInSecs : defaultRules.elapsedTimeSinceLastAdShownInSecs; var elapsedTimeSinceLastPurchaseInSecs = config.elapsedTimeSinceLastPurchaseInSecs != null ? config.elapsedTimeSinceLastPurchaseInSecs : defaultRules.elapsedTimeSinceLastPurchaseInSecs; var tutorialCheckEnabled = config.tutorialCheckEnabled != null ? config.tutorialCheckEnabled : defaultRules.tutorialCheckEnabled; config.minUserLtvInUsd = minUserLtvInUsd; config.elapsedTimeSinceCurrentLaunchInSecs = elapsedTimeSinceCurrentLaunchInSecs; config.elapsedTimeSinceAppInstallInSecs = elapsedTimeSinceAppInstallInSecs; config.elapsedTimeSinceAppInstallInDays = elapsedTimeSinceAppInstallInDays; config.elapsedTimeSinceLastAdShownInSecs = elapsedTimeSinceLastAdShownInSecs; config.elapsedTimeSinceLastPurchaseInSecs = elapsedTimeSinceLastPurchaseInSecs; config.tutorialCheckEnabled = tutorialCheckEnabled; // remove disabled rules from suppression rules. (disabled when set to -1) var disabledRules = disabledSuppressionRules(config); Object.keys(disabledRules).forEach(function (key) { delete config[key]; prettyPrint(key + " check is disabled", debug); }); return config; } function defaultSuppressionRules() { return { "minUserLtvInUsd": 0.99, // Greater or equal than this value will suppress loading/showing interstitial ads "elapsedTimeSinceCurrentLaunchInSecs": 60, // Less than this value will suppress showing interstitial ads "elapsedTimeSinceAppInstallInSecs": 600, // Less than this value will suppress loading/showing interstitial ads "elapsedTimeSinceAppInstallInDays": 30, // Less that this value will suppress showing banner ads "elapsedTimeSinceLastAdShownInSecs": 300, // Less than this value will suppress showing interstitial ads "elapsedTimeSinceLastPurchaseInSecs": 2592000, // 30 days - If payer and less than this value will suppress loading/showing interstitial ads "tutorialCheckEnabled": true // SDK will ignore the tutorial check if disabled }; } function disabledSuppressionRules(rules) { var disabledRules = {}; Object.keys(rules).forEach(function (key) { if (rules[key] == -1 || rules[key] == false) { disabledRules[key] = true; } }); return disabledRules; } /********************************************************* * Helper functions */ function getTimeDifferenceInSeconds(t1, t2) { return (t1 - t2) / 1000; } function getTimeDifferenceInDays(t1, t2) { return Math.floor((t1 - t2) / (3600*1000*24)) } function prettyPrint(obj, debug) { if (debug) { if (typeof console === "undefined") { var noop = function() {}; console = { log: noop, error: noop } } console.log(JSON.stringify(obj, null, 4)); } } function andOperation(obj) { var ret = true; Object.keys(obj).forEach(function (key) { ret &= obj[key]; }); return Boolean(ret); } function strToBool(value) { return value == 'true'; } function isNumber(x) { return typeof x === 'number'; } function isBoolean(x) { return typeof x === 'boolean' || (typeof x === 'object' && typeof x.valueOf() === 'boolean'); } function isBanner(adType) { return adType === 'banner'; }