/** * OGAds Intelligent Offer Optimization & Deterministic Pinning Engine * Centralized Rules & Fallback Backfill System * * Edit this file anytime to swap or reorder pinned offers across all 290 landing pages instantly! */ (function(window) { 'use strict'; var OGAdsRules = { // Total offers to display on the locker (default 5, configurable) SLOT_COUNT: 5, // Strictly pinned offer IDs per Geo + Device in designated 1-5 slot order PINNED_OFFERS: { // United States (US) iPhone / iPad 'US_IOS': [ 72798, // Slot 1: Modo Casino - KW Rotator (iOS CPI, 25.0% CVR) 15550, // Slot 2: Get A Chipotle Gift Card! RS (Email Submit, 40.0% CVR) 75099, // Slot 3: Get Towards Apple Pay RS (Email Submit, 14.3% CVR) 75883, // Slot 4: Have a chance to get a PayPal Gift Card! 75100 // Slot 5: Get Up To Towards DoorDash RS ], // United States (US) Android 'US_ANDROID': [ 74126, // Slot 1: Reco Social (Android CPE, 10.0% CVR, .23) 15550, // Slot 2: Get A Chipotle Gift Card! RS (Email Submit, 40.0% CVR) 75099, // Slot 3: Get Towards Apple Pay RS (Email Submit, 14.3% CVR) 74662, // Slot 4: Chick fil A Play (Android CPI, US) 75102 // Slot 5: Towards Shopping at Walmart! RS ], // United States (US) Desktop 'US_DESKTOP': [ 15550, // Get A Chipotle Gift Card! (40% CVR) 75099, // Get Towards Apple Pay (14.3% CVR) 75883, // Have a chance to get a PayPal Gift Card! 75100, // Get Up To Towards DoorDash 75102 // Towards Shopping at Walmart! ], // United Kingdom (UK) 'UK_IOS': [76191, 75660, 74646, 73229, 68019], 'UK_ANDROID': [76191, 75660, 74646, 73229, 68019], 'UK_DESKTOP': [76191, 73229, 75919], // Canada & Australia Tier 1 'CA_IOS': [72798, 15550, 75099, 75883, 75100], 'CA_ANDROID': [74126, 15550, 75099, 74662, 75102], 'AU_IOS': [72798, 15550, 75099, 75883, 75100], 'AU_ANDROID': [74126, 15550, 75099, 74662, 75102], // India (IN) - High-converting lightweight submits only (100% of Indian conversions) 'IN_ALL': [ 73653, // Score to have the chance to unlock special offers! 73111, // Tap to earn your bonus! (Email Submit) 73110, // Click to catch your coins! (Email Submit) 74883 // Score goals to get special offer! (Email Submit) ], 'IN_ANDROID': [73653, 73111, 73110, 74883], 'IN_IOS': [73653, 73111, 73110, 74883], // Pakistan (PK) - Native Urdu submit (3.85% CVR) + proven multi-geos 'PK_ALL': [ 65964, // !اپنے انعام کا دعوی کرنے کے لیے تھپتھپائیں (Urdu Email Submit) 73653, 73111, 73110 ], // Global Fallbacks 'GLOBAL_IOS': [72798, 15550, 75099], 'GLOBAL_ANDROID': [74126, 15550, 75099] }, // Blacklisted keywords for content lockers // Filters out offers that destroy conversion rates (CPE Level 10+, Banking/Crypto KYC, Personal Loans) NEGATIVE_KEYWORDS: [ 'lvl 10', 'level 10', 'lvl 15', 'level 15', 'lvl 20', 'level 20', 'reach level', 'complete level', 'kyc', 'aadhaar', 'pan card', 'personal loan', 'credit card required', 'first deposit' ], // Helper: Detect Device from User Agent detectDevice: function(ua) { ua = (ua || (typeof navigator !== 'undefined' ? navigator.userAgent : '')).toLowerCase(); if (/iphone|ipad|ipod/.test(ua)) return 'IOS'; if (/android/.test(ua)) return 'ANDROID'; return 'DESKTOP'; }, // Check if offer contains blacklisted keywords isOfferAllowed: function(offer) { if (!offer) return false; var text = ((offer.name || '') + ' ' + (offer.name_short || '') + ' ' + (offer.description || '') + ' ' + (offer.adcopy || '')).toLowerCase(); for (var i = 0; i < this.NEGATIVE_KEYWORDS.length; i++) { if (text.indexOf(this.NEGATIVE_KEYWORDS[i]) !== -1) { return false; } } return true; }, /** * Optimizes incoming offers from OGAds API: * 1. Detects country & device * 2. Finds matching pinned IDs * 3. Locks pinned offers into slots 1..N if active * 4. If pinned offers are capped/disabled, backfills remaining slots with highest EPC network offers * 5. Strips out negative keyword offers (Level 10 games, KYC apps) * 6. Returns exactly SLOT_COUNT offers */ optimizeOffers: function(apiOffers, context) { if (!Array.isArray(apiOffers) || apiOffers.length === 0) { return apiOffers || []; } context = context || {}; var country = (context.country || '').toUpperCase(); var device = (context.device || this.detectDevice(context.userAgent)).toUpperCase(); var maxSlots = this.SLOT_COUNT || 5; // 1. Determine pinned list key var pinnedIds = null; var keyExact = country + '_' + device; var keyCountryAll = country + '_ALL'; var keyGlobalDevice = 'GLOBAL_' + device; if (this.PINNED_OFFERS[keyExact]) { pinnedIds = this.PINNED_OFFERS[keyExact]; } else if (this.PINNED_OFFERS[keyCountryAll]) { pinnedIds = this.PINNED_OFFERS[keyCountryAll]; } else if (this.PINNED_OFFERS[keyGlobalDevice]) { pinnedIds = this.PINNED_OFFERS[keyGlobalDevice]; } // Map incoming offers by ID for fast lookup var offerMap = {}; apiOffers.forEach(function(o) { if (o && o.offerid) { offerMap[String(o.offerid)] = o; } }); var selectedOffers = []; var usedOfferIds = {}; // 2. Lock in pinned offers in strict designated order if (Array.isArray(pinnedIds)) { for (var i = 0; i < pinnedIds.length; i++) { var targetId = String(pinnedIds[i]); if (offerMap[targetId]) { selectedOffers.push(offerMap[targetId]); usedOfferIds[targetId] = true; if (selectedOffers.length >= maxSlots) break; } } } // 3. Fallback Backfill: If pinned offers are capped, disabled, or fewer than maxSlots if (selectedOffers.length < maxSlots) { var self = this; // Filter candidate offers: not already used, not blacklisted var candidates = apiOffers.filter(function(o) { if (!o || !o.offerid) return false; if (usedOfferIds[String(o.offerid)]) return false; return self.isOfferAllowed(o); }); // Sort candidates by highest EPC descending, then highest payout candidates.sort(function(a, b) { var epcA = parseFloat(a.epc) || 0; var epcB = parseFloat(b.epc) || 0; if (epcB !== epcA) return epcB - epcA; var payA = parseFloat(a.payout) || 0; var payB = parseFloat(b.payout) || 0; return payB - payA; }); // Fill remaining slots for (var j = 0; j < candidates.length && selectedOffers.length < maxSlots; j++) { selectedOffers.push(candidates[j]); usedOfferIds[String(candidates[j].offerid)] = true; } // If candidates were filtered out aggressively and we still need slots, relax blacklist as last resort if (selectedOffers.length < maxSlots) { for (var k = 0; k < apiOffers.length && selectedOffers.length < maxSlots; k++) { var off = apiOffers[k]; if (off && off.offerid && !usedOfferIds[String(off.offerid)]) { selectedOffers.push(off); usedOfferIds[String(off.offerid)] = true; } } } } return selectedOffers.slice(0, maxSlots); } }; // Expose globally if (typeof module !== 'undefined' && module.exports) { module.exports = OGAdsRules; } if (typeof window !== 'undefined') { window.OGAdsRules = OGAdsRules; } })(typeof window !== 'undefined' ? window : this);