SKAdNetwork कन्वर्जन वैल्यू मैपिंग: डायनेमिक SKAN स्कीमा को ऑटोमेट करें

opoinstall
2026-08-25
5 min read

एक MMP स्वचालित रूप से SKAdNetwork स्कीमा कैसे मैप करता है? एक मोबाइल मेजरमेंट पार्टनर (MMP) या एट्रिब्यूशन बैकएंड, इन-ऐप इवेंट्स और रेवेन्यू टीयर को सेंट्रलाइज्ड कंसोल पर डायनेमिक, वर्शंड JSON कॉन्फ़िगरेशन स्कीमा में ट्रांसलेट करके SKAdNetwork स्कीमा मैपिंग को ऑटोमेट करता है। मोबाइल SDK लॉन्च होने पर इस कॉन्फ़िगरेशन को प्राप्त करता है और रनटाइम पर स्थानीय रूप से कन्वर्जन नियमों का मूल्यांकन करता है, जिससे समर्थित कन्वर्जन-नियम परिवर्तन नए बाइनरी ऐप रिलीज़ की आवश्यकता के बिना प्रभावी हो जाते हैं।

एक SKAdNetwork कन्वर्जन वैल्यू स्कीमा एक वेंडर- या एप्लिकेशन-स्तरीय रूलसेट है जो इन-ऐप उपयोगकर्ता व्यवहारों—जैसे रेवेन्यू ट्रांजेक्शन, ऑनबोर्डिंग मीलस्टोन, या फ़ीचर एंगेजमेंट—को Apple के 6-बिट फाइन-ग्रेनीड वैल्यू (0 से 63) और 3-टियर कोर्स-ग्रेनीड वैल्यू (low, medium, high) पर मैप करता है। डायनेमिक मैपिंग आर्किटेक्चर क्लाउड बैकएंड से क्लाइंट SDK में वर्शंड कॉन्फ़िगरेशन फ़ाइलों को वितरित करते हैं, जिससे संकलित iOS एप्लिकेशन बाइनरी के भीतर कन्वर्जन लॉजिक को हार्डकोड करने की आवश्यकता समाप्त हो जाती है।

शब्द परिभाषा
SKAdNetwork गोपनीयता-संरक्षित विज्ञापन अभियान एट्रिब्यूशन के लिए Apple का प्लेटफ़ॉर्म-स्तरीय फ़्रेमवर्क।
कन्वर्जन वैल्यू स्कीमा इन-ऐप इवेंट मीलस्टोन को फाइन और कोर्स वैल्यू पर मैप करने वाला एक वेंडर- या ऐप-परिभाषित कॉन्फ़िगरेशन।
डायनेमिक स्कीमा मैपिंग SDK के माध्यम से कन्वर्जन नियमों का स्वचालित वितरण और रनटाइम मूल्यांकन।
विंडो लॉकिंग एक API पैरामीटर (lockWindow: true) जो सक्रिय कन्वर्जन विंडो को समय से पहले अंतिम रूप देता है।

स्वचालित SKAdNetwork कन्वर्जन वैल्यू मैपिंग का आर्किटेक्चर

Apple प्लेटफ़ॉर्म लेयर को वेंडर स्कीमा लेयर से अलग करना

एक मजबूत कन्वर्जन वैल्यू इंजन को डिज़ाइन करने के लिए, इंजीनियरिंग टीमों को Apple के मूल फ़्रेमवर्क नियमों को वेंडर-स्तरीय स्कीमा एब्स्ट्रक्शन से अलग करना होगा:

  • Apple प्लेटफ़ॉर्म लेयर: मुख्य ऑपरेटिंग सिस्टम प्रिमिटिव को नियंत्रित करती है, जिसमें तीन क्रमिक कन्वर्जन विंडो (पहले लॉन्च के बाद Day 0–2, Day 3–7, Day 8–35), 6-बिट फाइन वैल्यू (0–63), कोर्स वैल्यू (low, medium, high), पोस्टबैक डेटा टीयर, और SKAdNetwork.updatePostbackConversionValue API शामिल हैं।
  • वेंडर स्कीमा लेयर: एप्लिकेशन-परिभाषित व्यावसायिक नियमों को शामिल करती है, जैसे रेवेन्यू बकेटिंग, ऑनबोर्डिंग फ़नल प्रगति, बिटवाइज फ़्लैग एलोकेशन, रिमोट JSON सिंक्रोनाइज़ेशन, और क्लाइंट-साइड नियम मूल्यांकन।
┌────────────────────────────────────────┐
│                           Vendor Schema Layer                                  │
│  [MMP / Analytics Console] ──► [Publishes Versioned JSON Configuration]     │
│                                              │                                │
│  [Client Mobile SDK]       ──► [Evaluates In-App Events Locally in Memory]  │
└──────────────────────────────────────┬─┘
                                       │ (Calculates Fine, Coarse, & Lock)
                                       ▼
┌────────────────────────────────────────┐
│                           Apple Platform Layer                                 │
│  [StoreKit Framework]      ──► [SKAdNetwork.updatePostbackConversionValue]  │
│  [Operating System]        ──► [Manages Conversion Windows & Timers]        │
│  [System]                  ──► [Prepares and Sends Signed Postback]         │
└────────────────────────────────────────┘

MMP कंसोल से StoreKit तक डायनेमिक SKAN स्कीमा मैपिंग

हार्डकोडेड कन्वर्जन लॉजिक की कमियां

iOS एप्लिकेशन टारगेट के भीतर सीधे कन्वर्जन लॉजिक को हार्डकोड करना महत्वपूर्ण परिचालन सीमाएं पैदा करता है:

  • ऐप स्टोर रिव्यू निर्भरता: रेवेन्यू थ्रेशोल्ड, इवेंट वेट, या विंडो-लॉक ट्रिगर में किसी भी संशोधन के लिए एक संपूर्ण बाइनरी रिलीज़ चक्र की आवश्यकता होती है।
  • वर्शन फ़्रैगमेंटेशन: प्रोडक्शन में कई ऐतिहासिक ऐप वर्शन परस्पर विरोधी कन्वर्जन सिमेंटिक्स प्रसारित करते हैं, जिससे डाउनस्ट्रीम रिपोर्टिंग मॉडल दूषित होते हैं।
  • ऑप्टिमाइज़ेशन अनम्यता: ग्रोथ टीमें वास्तविक समय के विपणन प्रदर्शन के जवाब में एंगेजमेंट-केंद्रित और मुद्रीकरण-केंद्रित अभियानों के बीच कन्वर्जन रणनीतियों को समायोजित नहीं कर सकती हैं।

डायनेमिक कॉन्फ़िगरेशन डिलीवरी पाइपलाइन

स्वचालित मैपिंग आर्किटेक्चर बहु-चरणीय पाइपलाइन के माध्यम से संकलित बाइनरी से कन्वर्जन लॉजिक को अलग करते हैं:

  1. कंसोल कॉन्फ़िगरेशन: मार्केटर्स और विश्लेषक सेंट्रलाइज्ड डैशबोर्ड पर इवेंट वेट, मुद्रा टीयर और विंडो-लॉक नियमों को कॉन्फ़िगर करते हैं।
  2. स्कीमा वर्शनिंग और पिनिंग: बैकएंड एक वर्शंड JSON कॉन्फ़िगरेशन पेलोड प्रकाशित करता है। उपयोगकर्ता के 35-दिन के कन्वर्जन लाइफसाइकिल के दौरान सिमेंटिक ड्रिफ्ट को रोकने के लिए, एक मजबूत वेंडर कार्यान्वयन प्रारंभिक कन्वर्जन विंडो के दौरान स्थापित सक्रिय स्कीमा कॉन्फ़िगरेशन को पिन करता है, यह सुनिश्चित करता है कि ऐप रीस्टार्ट होने पर भी सटीक मैपिंग नियम उपलब्ध रहें।
  3. क्लाइंट इंजेशन और कैशेइंग: मोबाइल SDK ऐप आरंभीकरण पर सक्रिय स्कीमा डाउनलोड करता है और स्थानीय लगातार स्टोरेज में कॉन्फ़िगरेशन पेलोड और वर्शन मेटाडेटा दोनों को कैश करता है।
  4. स्थानीय नियम मूल्यांकन: जब इन-ऐप इवेंट होते हैं, तो SDK इवेंट निष्पादन पथ में सिंक्रोनस रिमोट-कॉन्फ़िगरेशन अनुरोध जोड़े बिना, कैश्ड रूलसेट के खिलाफ स्थानीय रूप से उनका मूल्यांकन करता है।

हार्डकोडेड SKAN लॉजिक बनाम डायनेमिक स्कीमा कॉन्फ़िगरेशन

यह भी देखें: SKAdNetwork ──> मोबाइल एट्रिब्यूशन आर्किटेक्चर

SKAN 4.0 विंडो में डायनेमिक कन्वर्जन वैल्यू स्कीमा डिज़ाइन करना

मल्टी-विंडो स्कीमा विभाजन

SKAdNetwork 4.0 ऐप के पहले लॉन्च से जुड़ी तीन क्रमिक विंडो में कन्वर्जन माप की संरचना करता है:

  • विंडो 1 (Day 0–2): पहले लॉन्च के बाद पहले 48 घंटे।
  • विंडो 2 (Day 3–7): पहले लॉन्च के बाद 48 से 168 घंटे।
  • विंडो 3 (Day 8–35): पहले लॉन्च के बाद 168 से 840 घंटे।

एक डायनेमिक स्कीमा इंजन इन विंडो में नियमों को विभाजित करता है, प्रारंभिक एप्लिकेशन लॉन्च के बाद से बीते हुए समय के आधार पर उचित वैल्यू गणना निष्पादित करता है।

विंडो 1 (Day 0–2): फाइन और कोर्स वैल्यू की संरचना करना

फाइन-ग्रेनीड कन्वर्जन वैल्यू का खुलासा करने के लिए विंडो 1 एकमात्र कन्वर्जन विंडो है। विंडो 1 के लिए कॉन्फ़िगरेशन दो समवर्ती मैपिंग को परिभाषित करता है:

  • फाइन-ग्रेनीड मैपिंग (0–63): प्रारंभिक मुद्रीकरण टीयर, ऑनबोर्डिंग मीलस्टोन, या समग्र सहभागिता स्कोर को कैप्चर करने वाले उच्च-रिज़ॉल्यूशन नियम।
  • कोर्स-ग्रेनीड मैपिंग (low, medium, high): कम-ग्रेनुएलिटी फ़ॉलबैक स्थितियां जिनका खुलासा तब किया जाता है जब असाइन किया गया पोस्टबैक डेटा टीयर फाइन-ग्रेनीड रिपोर्टिंग की अनुमति नहीं देता है।

विंडो 2 (Day 3–7) और 3 (Day 8–35): कोर्स-ग्रेनीड लाइफसाइकिल ट्रैकिंग

दूसरा और तीसरा पोस्टबैक फाइन-ग्रेनीड कन्वर्जन वैल्यू को उजागर नहीं करते हैं; पात्र डेटा टीयर के लिए, वे केवल कोर्स वैल्यू का खुलासा करते हैं।

विंडो 2 और 3 के लिए स्कीमा दीर्घकालिक प्रतिधारण और मुद्रीकरण मीलस्टोन पर ध्यान केंद्रित करते हैं:

  • विंडो 2 कोर्स मैपिंग: मिड-फ़नल रिटेंशन का मूल्यांकन करता है (उदा., low = Day 3–7 पर सक्रिय; medium = 3 सत्र पूरे किए; high = बार-बार खरीदारी या ट्रायल कनवर्ट हुआ)।
  • विंडो 3 कोर्स मैपिंग: लॉन्ग-टेल रिटेंशन और सब्सक्रिप्शन नवीनीकरण का मूल्यांकन करता है (उदा., low = Day 8–35 पर बनाए रखा गया; medium = लेवल मीलस्टोन पहुंचा; high = सक्रिय भुगतान करने वाला सब्सक्राइबर)।

कन्वर्जन स्कीमा को कॉन्फ़िगर करने वाले डेवलपर्स मल्टी-विंडो नियम संरचनाओं पर तकनीकी दिशानिर्देशों के लिए SKAN कन्वर्जन मैपिंग दस्तावेज़ से परामर्श कर सकते हैं।

SKAN 4 कन्वर्जन विंडो फाइन और कोर्स वैल्यू मैपिंग


वेंडर-परिभाषित एन्कोडिंग मॉडल: रेवेन्यू बकेटिंग, फ़नल और बिटवाइज लॉजिक

ये एन्कोडिंग मॉडल Apple द्वारा निर्धारित स्कीमा प्रकारों के बजाय वेंडर- और एप्लिकेशन-स्तरीय डिज़ाइन पैटर्न का प्रतिनिधित्व करते हैं।

रेवेन्यू-आधारित स्कीमा

रेवेन्यू स्कीमा संचयी खरीद राशि में उपलब्ध फाइन-ग्रेनीड वैल्यू आवंटित करते हैं:

  • लीनियर बकेटिंग: रेवेन्यू रेंज को समान अंतरालों में विभाजित करता है (उदा., $96.00 तक $1.50 की वृद्धि के 64 बकेट)। अनुमानित ट्रांजेक्शन आकार वाले अनुप्रयोगों के लिए आदर्श।
  • लॉगरिदमिक बकेटिंग: उच्च-मूल्य वाले लेनदेन के लिए बकेट रेंज का विस्तार करते हुए कम लागत वाली खरीद के लिए दानेदार बकेट आवंटित करता है (उदा., वैल्यू 1–20 $0.99–$19.99 को कवर करते हैं; वैल्यू 21–50 $20.00–$100.00 को कवर करते हैं; वैल्यू 51–63 $100.00–$1000.00+ को कवर करते हैं)।
  • पर्सेंटाइल-आधारित बकेटिंग: ऐतिहासिक उपयोगकर्ता खरीद वितरण को अनुभवजन्य मुद्रीकरण वक्रों के आधार पर कोहर्ट सेगमेंट में मैप करता है।

फ़नल प्रोग्रेसन स्कीमा और वैल्यू डायरेक्शनलिटी

SKAdNetwork 3 और उससे पहले, Apple को यह आवश्यक था कि कन्वर्जन वैल्यू मोनोलाइटिक रूप से बढ़ें। SKAdNetwork 4.0 में, Apple ने इस प्रतिबंध को हटा दिया, जिससे विंडो 1 में कन्वर्जन वैल्यू को बाद के API कॉल में बढ़ने या घटने की अनुमति मिली।

हालांकि, कई एट्रिब्यूशन स्कीमा जानबूझकर एक वेंडर-स्तरीय डिज़ाइन सम्मेलन के रूप में मोनोलाइटिक प्रगति को लागू करते हैं ताकि यह सुनिश्चित किया जा सके कि उच्च वैल्यू लगातार मजबूत व्यावसायिक परिणामों का प्रतिनिधित्व करते हैं:

  • वैल्यू 0: ऐप इंस्टॉल और खोला गया।
  • वैल्यू 10: पंजीकरण पूरा हुआ।
  • वैल्यू 20: ऑनबोर्डिंग ट्यूटोरियल समाप्त।
  • वैल्यू 30: भुगतान विधि जोड़ी गई।
  • वैल्यू 45: कार्ट में आइटम जोड़ा गया।
  • वैल्यू 63: प्रारंभिक चेकआउट पूरा हुआ।

बिटवाइज कैटेगोरिकल स्कीमा

बिटवाइज स्कीमा 6-बिट पूर्णांक (26=642^6 = 64) को छह स्वतंत्र बूलियन फ़्लैग के रूप में मानता है (b5b4b3b2b1b0b_5 b_4 b_3 b_2 b_1 b_0):

बिट स्थिति बाइनरी वेट मैप किया गया इन-ऐप व्यवहार
बिट 0 (b0b_0) 1 (0b000001) उपयोगकर्ता ने पंजीकरण पूरा किया
बिट 1 (b1b_1) 2 (0b000010) उपयोगकर्ता ने पुश नोटिफिकेशन सक्षम किया
बिट 2 (b2b_2) 4 (0b000100) उपयोगकर्ता ने विशलिस्ट में आइटम जोड़ा
बिट 3 (b3b_3) 8 (0b001000) उपयोगकर्ता ने रेफ़रल लिंक साझा किया
बिट 4 (b4b_4) 16 (0b010000) उपयोगकर्ता ने इन-ऐप खरीदारी पूरी की
बिट 5 (b5b_5) 32 (0b100000) उपयोगकर्ता ने प्रीमियम ट्रायल की सदस्यता ली

नीचे दिया गया वर्शंड JSON पेलोड एक बहु-विंडो डायनेमिक कॉन्फ़िगरेशन दस्तावेज़ को दर्शाता है:

{
  "schema_version": "4.0.1",
  "app_id": "1234567890",
  "currency": "USD",
  "windows": {
    "window_1": {
      "mode": "hybrid_revenue_and_funnel",
      "fine_mapping": [
        { "event": "app_open", "min_revenue_cents": 0, "fine_value": 0, "lock": false },
        { "event": "registration_complete", "min_revenue_cents": 0, "fine_value": 10, "lock": false },
        { "event": "tutorial_complete", "min_revenue_cents": 0, "fine_value": 20, "lock": false },
        { "event": "purchase", "min_revenue_cents": 99, "fine_value": 30, "lock": false },
        { "event": "purchase", "min_revenue_cents": 999, "fine_value": 45, "lock": false },
        { "event": "purchase", "min_revenue_cents": 4999, "fine_value": 63, "lock": true }
      ],
      "coarse_mapping": {
        "low": { "events": ["app_open", "registration_complete"] },
        "medium": { "events": ["tutorial_complete"] },
        "high": { "events": ["purchase"] }
      }
    },
    "window_2": {
      "mode": "coarse_retention_and_monetization",
      "coarse_mapping": {
        "low": { "events": ["app_open"], "lock": false },
        "medium": { "events": ["session_milestone"], "lock": false },
        "high": { "events": ["repeat_purchase"], "lock": true }
      }
    },
    "window_3": {
      "mode": "coarse_long_tail_ltv",
      "coarse_mapping": {
        "low": { "events": ["app_open"], "lock": false },
        "medium": { "events": ["level_milestone"], "lock": false },
        "high": { "events": ["subscription_active"], "lock": true }
      }
    }
  }
}

डायनेमिक SDK कॉन्फ़िगरेशन: रनटाइम पर रिमोट कॉन्फ़िगरेशन को प्राप्त करना और उनका मूल्यांकन करना

क्लाइंट-साइड नियम मूल्यांकन मैकेनिक्स

एट्रिब्यूशन SDK एप्लिकेशन रनटाइम के भीतर स्थानीय रूप से कन्वर्जन नियमों का मूल्यांकन करते हैं:

  • इवेंट पथ पर कोई सिंक्रोनस रिमोट-कॉन्फ़िगरेशन फ़ेच नहीं: इन-ऐप क्रियाएं एप्लिकेशन निष्पादन को अवरुद्ध किए बिना तुरंत StoreKit API को कॉल करते हुए, सक्रिय रूलसेट के खिलाफ स्थानीय इन-मेमोरी मूल्यांकन को ट्रिगर करती हैं।
  • डेटा न्यूनीकरण: यहां दिखाए गए SKAdNetwork कन्वर्जन-अपडेट पथ के लिए, कच्चे इवेंट इनपुट का स्थानीय रूप से मूल्यांकन किया जा सकता है और केवल परिणामी कन्वर्जन वैल्यू को StoreKit में पास करने की आवश्यकता होती है। यह अपने आप में SDK द्वारा कार्यान्वित अन्य एनालिटिक्स डेटा प्रवाह का वर्णन या सीमा तय नहीं करता है।

ऑफ़लाइन स्थिति और स्थानीय दृढ़ता को संभालना

जब कोई एप्लिकेशन ऑफ़लाइन या खराब नेटवर्क स्थिति में लॉन्च होता है:

  1. SDK स्थानीय दृढ़ता में स्वतंत्र रूप से पहले-लंच टाइमस्टैम्प एंकर को इनिशियलाइज करता है।
  2. SDK लगातार स्थानीय स्टोरेज से पिन किए गए कॉन्फ़िगरेशन स्कीमा को लोड करता है, यह सत्यापित करता है कि कैश्ड पेलोड पिन किए गए स्कीमा वर्शन से मेल खाता है।
  3. यदि ऑफ़लाइन होने पर इन-ऐप इवेंट होते हैं, तो SDK कैश्ड रूलसेट के खिलाफ उनका मूल्यांकन करता है और तुरंत StoreKit अपडेट API को कॉल करता है।
  4. पोस्टबैक तैयारी और वितरण सिस्टम-प्रबंधित और असमकालिक रहते हैं; ऐप को स्वयं पोस्टबैक भेजने की आवश्यकता नहीं है।

नीचे दिया गया स्विफ्ट कार्यान्वयन एक बहु-विंडो स्कीमा मूल्यांकन इंजन को प्रदर्शित करता है जो ठीक और मोटे मूल्यों की गणना करता है, विंडो-विशिष्ट लॉक राज्यों को प्रबंधित करता है, पिन किए गए स्कीमा कॉन्फ़िगरेशन को बनाए रखता है, और सफल StoreKit निष्पादन पर ही राज्य अपडेट को प्रतिबद्ध करता है:

import Foundation
import StoreKit

// MARK: - Schema Configuration Models

struct SKANSchemaConfig: Codable {
    let schemaVersion: String
    let appId: String
    let currency: String
    let windows: SchemaWindows

    enum CodingKeys: String, CodingKey {
        case schemaVersion = "schema_version"
        case appId = "app_id"
        case currency, windows
    }
}

struct SchemaWindows: Codable {
    let window1: Window1Config
    let window2: WindowCoarseConfig
    let window3: WindowCoarseConfig

    enum CodingKeys: String, CodingKey {
        case window1 = "window_1"
        case window2 = "window_2"
        case window3 = "window_3"
    }
}

struct Window1Config: Codable {
    let mode: String
    let fineMapping: [FineRule]
    let coarseMapping: CoarseRuleGroup

    enum CodingKeys: String, CodingKey {
        case mode
        case fineMapping = "fine_mapping"
        case coarseMapping = "coarse_mapping"
    }
}

struct FineRule: Codable {
    let event: String
    let minRevenueCents: Int
    let fineValue: Int
    let lock: Bool

    enum CodingKeys: String, CodingKey {
        case event
        case minRevenueCents = "min_revenue_cents"
        case fineValue = "fine_value"
        case lock
    }
}

struct WindowCoarseConfig: Codable {
    let mode: String
    let coarseMapping: [String: CoarseRule]

    enum CodingKeys: String, CodingKey {
        case mode
        case coarseMapping = "coarse_mapping"
    }
}

struct CoarseRuleGroup: Codable {
    let low: CoarseRule
    let medium: CoarseRule
    let high: CoarseRule
}

struct CoarseRule: Codable {
    let events: [String]?
    let lock: Bool?
}

// MARK: - Multi-Window SKAN 4.0 Schema Engine

final class SKANSchemaEngine {

    static let shared = SKANSchemaEngine()
    private init() {}

    private var activeSchema: SKANSchemaConfig?
    private var firstLaunchDate: Date?
    private var lockedWindows = Set<Int>()
    private var lastRecordedFineValue: Int = 0
    private var pinnedSchemaVersion: String?

    /// Initializes the first-launch timestamp anchor independently of remote configuration fetches
    func initializeLifecycleAnchor() {
        let defaults = UserDefaults.standard
        if let storedLaunch = defaults.object(forKey: "skan_first_launch_date") as? Date {
            self.firstLaunchDate = storedLaunch
        } else {
            let now = Date()
            self.firstLaunchDate = now
            defaults.set(now, forKey: "skan_first_launch_date")
        }

        let lockedArray = defaults.array(forKey: "skan_locked_windows") as? [Int] ?? []
        self.lockedWindows = Set(lockedArray)
        self.lastRecordedFineValue = defaults.integer(forKey: "skan_last_fine_value")
        self.pinnedSchemaVersion = defaults.string(forKey: "skan_pinned_schema_version")

        // Restore previously cached schema payload if it matches the pinned version
        if let pinnedVersion = self.pinnedSchemaVersion,
           let cachedData = defaults.data(forKey: "skan_cached_schema_payload"),
           let cachedSchema = try? JSONDecoder().decode(SKANSchemaConfig.self, from: cachedData),
           cachedSchema.schemaVersion == pinnedVersion {
            self.activeSchema = cachedSchema
        }
    }

    /// Loads active schema, persisting the pinned payload to maintain consistency across the 35-day lifecycle
    func configure(schema: SKANSchemaConfig) {
        let defaults = UserDefaults.standard
        if let pinned = pinnedSchemaVersion {
            // If already pinned, accept only schemas matching the pinned version
            if pinned == schema.schemaVersion {
                self.activeSchema = schema
                if let data = try? JSONEncoder().encode(schema) {
                    defaults.set(data, forKey: "skan_cached_schema_payload")
                }
            }
        } else {
            // Pin the initial schema version for this lifecycle
            self.activeSchema = schema
            self.pinnedSchemaVersion = schema.schemaVersion
            defaults.set(schema.schemaVersion, forKey: "skan_pinned_schema_version")
            if let data = try? JSONEncoder().encode(schema) {
                defaults.set(data, forKey: "skan_cached_schema_payload")
            }
        }
    }

    /// Determines the active conversion window based on elapsed time from first launch
    private var currentWindowIndex: Int {
        guard let firstLaunch = firstLaunchDate else { return 0 }
        let elapsedHours = Date().timeIntervalSince(firstLaunch) / 3600.0

        switch elapsedHours {
        case 0.0..<48.0:
            return 1
        case 48.0..<168.0:
            return 2
        case 168.0...840.0:
            return 3
        default:
            return 0 // Window closed (>35 days)
        }
    }

    /// Evaluates an in-app event against the active schema for the current window
    func trackEvent(name: String, revenueCents: Int = 0) {
        guard #available(iOS 16.1, *),
              let schema = activeSchema else { return }

        let window = currentWindowIndex
        guard window >= 1 && window <= 3, !lockedWindows.contains(window) else { return }

        var targetFineValue: Int?
        var targetCoarseValue: SKAdNetwork.CoarseConversionValue?
        var shouldLock = false
        var matchedRule = false

        if window == 1 {
            // Window 1: Evaluate fine-grained rules with highest-threshold precedence
            let matchingFineRules = schema.windows.window1.fineMapping
                .filter { $0.event == name && revenueCents >= $0.minRevenueCents }
                .sorted { $0.minRevenueCents < $1.minRevenueCents }

            if let highestRule = matchingFineRules.last {
                targetFineValue = highestRule.fineValue
                if highestRule.lock { shouldLock = true }
                matchedRule = true
            }

            // Window 1: Evaluate coarse-grained rules explicitly
            if schema.windows.window1.coarseMapping.high.events?.contains(name) == true {
                targetCoarseValue = .high
                matchedRule = true
            } else if schema.windows.window1.coarseMapping.medium.events?.contains(name) == true {
                targetCoarseValue = .medium
                matchedRule = true
            } else if schema.windows.window1.coarseMapping.low.events?.contains(name) == true {
                targetCoarseValue = .low
                matchedRule = true
            }
        } else {
            // Windows 2 & 3: Evaluate coarse rules only
            let coarseConfig = (window == 2) ? schema.windows.window2 : schema.windows.window3
            
            if let highRule = coarseConfig.coarseMapping["high"], highRule.events?.contains(name) == true {
                targetCoarseValue = .high
                if highRule.lock == true { shouldLock = true }
                matchedRule = true
            } else if let medRule = coarseConfig.coarseMapping["medium"], medRule.events?.contains(name) == true {
                targetCoarseValue = .medium
                if medRule.lock == true { shouldLock = true }
                matchedRule = true
            } else if let lowRule = coarseConfig.coarseMapping["low"], lowRule.events?.contains(name) == true {
                targetCoarseValue = .low
                if lowRule.lock == true { shouldLock = true }
                matchedRule = true
            }
        }

        // If no explicit rule matched for this event, do not trigger a StoreKit update
        guard matchedRule else { return }

        let fineToSubmit = targetFineValue ?? (window == 1 ? lastRecordedFineValue : 0)
        let clampedFine = max(0, min(63, fineToSubmit))
        let coarseToSubmit = targetCoarseValue ?? .low

        // Dispatch StoreKit conversion update
        // Note: StoreKit ignores the fineValue parameter after Window 1
        SKAdNetwork.updatePostbackConversionValue(
            clampedFine,
            coarseValue: coarseToSubmit,
            lockWindow: shouldLock
        ) { [weak self] error in
            guard let self = self else { return }
            if let error = error {
                print("StoreKit conversion update failed: \(error.localizedDescription)")
            } else {
                // Commit local state only after StoreKit successfully accepts the update
                DispatchQueue.main.async {
                    if window == 1 {
                        self.lastRecordedFineValue = clampedFine
                        UserDefaults.standard.set(clampedFine, forKey: "skan_last_fine_value")
                    }
                    if shouldLock {
                        self.lockedWindows.insert(window)
                        UserDefaults.standard.set(Array(self.lockedWindows), forKey: "skan_locked_windows")
                    }
                    print("SKAN 4.0 update succeeded: Window=\(window), Fine=\(clampedFine), Coarse=\(coarseToSubmit.rawValue), Locked=\(shouldLock)")
                }
            }
        }
    }
}

SKAN lockWindow समय और प्रारंभिक पोस्टबैक तैयारी

पोस्टबैक तैयारी को तेज करने के लिए lockWindow निष्पादन को ऑटोमेट करना

lockWindow पैरामीटर का परिचालन मैकेनिक्स

जब कोई ऐप lockWindow: true के साथ updatePostbackConversionValue(_:coarseValue:lockWindow:) को कॉल करता है, तो अपडेट सक्रिय विंडो के लिए अंतिम कन्वर्जन-वैल्यू अपडेट बन जाता है। ऑपरेटिंग सिस्टम तुरंत पोस्टबैक तैयार करता है और उस विंडो के शेष भाग के लिए अतिरिक्त कन्वर्जन-वैल्यू अपडेट को अनदेखा करता है।

Default Window 1 (No Lock):
[First Launch] ─────────────── 48 Hours Open ───────────────► [Closes] ──► Delay (24-48h) ──► Postback 1

Locked Window 1 (Purchase at Hour 6):
[First Launch] ── 6h (Lock: true) ──► [Conversion Locked / Postback Prepared] ──► Delay (24-48h) ──► Postback 1 Sent Sooner

स्वचालित विंडो लॉकिंग में रणनीतिक ट्रेड-ऑफ़

  • त्वरित पोस्टबैक प्रेषण: किसी कन्वर्जन को जल्दी अंतिम रूप देने से Apple के यादृच्छिक पोस्टबैक विलंब को तुरंत शुरू करने की अनुमति मिलती है, जिससे विज्ञापन नेटवर्क को जल्द ही कन्वर्जन डेटा मिलता है।
  • विंडो स्वतंत्रता: वर्तमान विंडो को लॉक करने से अगली विंडो की शुरुआत आगे नहीं बढ़ती है; Window 1 के लॉक होने के समय की परवाह किए बिना Window 2 अभी भी Day 3 पर शुरू होती है।
  • ऑब्जर्वेशन ट्रंकेशन: एक बार विंडो लॉक हो जाने के बाद, सिस्टम उस कन्वर्जन विंडो के शेष भाग के लिए बाद के कन्वर्जन-वैल्यू अपडेट कॉल को अनदेखा कर देता है। इन-ऐप इवेंट होना जारी रह सकते हैं, लेकिन वे उस विंडो के SKAdNetwork कन्वर्जन स्थिति को और नहीं बदल सकते हैं।

AdAttributionKit के साथ SKAN स्कीमा का समन्वय करना

Apple का विकसित होता एट्रिब्यूशन स्टैक

Apple अब ऐप स्टोर और वैकल्पिक ऐप मार्केटप्लेस पर ऐप विज्ञापन अभियानों के लिए AdAttributionKit की सिफारिश करता है। SKAdNetwork मौजूदा एकीकरण और इंटरऑपरेबिलिटी के लिए प्रासंगिक बना हुआ है, इसलिए डायनेमिक मैपिंग इंजनों को अपने व्यावसायिक-नियम लेयर को फ्रेमवर्क-विशिष्ट कन्वर्जन API से अलग रखना चाहिए:

  • साझा वैल्यू आयाम: दोनों फ़्रेमवर्क 6-बिट फाइन-ग्रेनीड वैल्यू (0 से 63) और 3-टियर कोर्स-ग्रेनीड वैल्यू (low, medium, high) का मूल्यांकन करते हैं।
  • अलग API लेयर: SKAdNetwork SKAdNetwork.updatePostbackConversionValue का उपयोग करता है, जबकि AdAttributionKit Postback.updateConversionValue का उपयोग करता है।
  • ब्रिजिंग व्यवहार: यदि कोई एकीकरण दोनों फ़्रेमवर्क का समर्थन करता है, तो Apple दस्तावेज़ीकृत SKAdNetwork से AdAttributionKit ब्रिजिंग व्यवहार को ध्यान में रखते हुए, दोनों फ़्रेमवर्क के कन्वर्जन-अपडेट API को कॉल करने की सलाह देता है।

तुलनात्मक निर्णय मैट्रिक्स: हार्डकोडेड क्लाइंट लॉजिक बनाम डायनेमिक कॉन्फ़िगरेशन

मूल्यांकन आयाम हार्डकोडेड क्लाइंट-साइड लॉजिक डायनेमिक स्कीमा कॉन्फ़िगरेशन
स्कीमा संशोधन गति ऐप स्टोर रिव्यू की आवश्यकता है (दिनों से सप्ताह) नए बाइनरी रिलीज़ की आवश्यकता के बिना समर्थित नियम परिवर्तनों के लिए रिमोट अपडेट
परीक्षण और पुनरावृत्ति चपलता उच्च घर्षण / उच्च इंजीनियरिंग ओवरहेड वर्शन- और कोहर्ट-पृथक नियमों के साथ नियंत्रित स्कीमा प्रयोग
मल्टी-विंडो समन्वय स्विफ्ट में जटिल मैनुअल स्टेट मशीन स्वचालित लाइफसाइकिल-अवेयर इंजन
स्वचालित विंडो लॉकिंग निश्चित, अनम्य नियम ट्रिगर डायनेमिक, इवेंट-ट्रिगर लॉक नियम
क्रॉस-फ्रेमवर्क समता फ्रेमवर्क में खंडित कोड एकीकृत क्लाउड कॉन्फ़िगरेशन मैट्रिक्स

अक्सर पूछे जाने वाले प्रश्न (FAQ)

क्या होता है जब कोई उपयोगकर्ता अलग-अलग कन्वर्जन वैल्यू पर मैप किए गए कई इवेंट को ट्रिगर करता है?
SKAdNetwork 4.0 में, Apple क्रमिक कॉल में Window 1 में कन्वर्जन वैल्यू को बढ़ने या घटने की अनुमति देता है। हालांकि, एक एट्रिब्यूशन स्कीमा वेंडर डिज़ाइन कन्वेंशन के रूप में मोनोलाइटिक प्रगति को लागू कर सकता है, जिस स्थिति में क्लाइंट SDK कन्वर्जन वैल्यू को केवल तभी अपडेट करता है जब आने वाला इवेंट वर्तमान रिकॉर्डेड स्थिति से अधिक वैल्यू उत्पन्न करता है।
यदि ऐप ऑफ़लाइन है, तो क्या स्वचालित स्कीमा कन्वर्जन वैल्यू को अपडेट कर सकता है?
हाँ। यदि SDK के पास एक वैध कैश्ड स्कीमा है, तो वह नए स्कीमा को सिंक्रोनस रूप से प्राप्त किए बिना इवेंट का मूल्यांकन कर सकता है और StoreKit को कॉल कर सकता है। SKAdNetwork पोस्टबैक तैयारी और वितरण सिस्टम-प्रबंधित और असमकालिक रहते हैं।
एक स्वचालित स्कीमा वैश्विक उपयोगकर्ताओं के लिए मुद्रा रूपांतरण को कैसे संभालता है?
एक स्वचालित स्कीमा इंजन रेवेन्यू बकेट थ्रेशोल्ड का मूल्यांकन करने से पहले डिवाइस पर सभी इन-ऐप खरीदारी राशि को एक मानक आधार मुद्रा (जैसे USD सेंट) में सामान्य करता है या पूर्व-रूपांतरित पूर्णांक वैल्यू पास करता है।

सारांश और निर्णय फ़्रेमवर्क

SKAdNetwork कन्वर्जन वैल्यू मैपिंग को ऑटोमेट करना मोबाइल बाइनरी रिलीज़ चक्र से ग्रोथ एक्सपेरिमेंटेशन को अलग करता है। सेंट्रलाइज्ड एट्रिब्यूशन डैशबोर्ड से डायनेमिक स्कीमा वितरित करके और SDK के भीतर स्थानीय रूप से उनका मूल्यांकन करके, इंजीनियरिंग टीमें रेवेन्यू बकेट को ठीक कर सकती हैं, फ़नल मीलस्टोन को अनुकूलित कर सकती हैं, और स्वचालित विंडो लॉक को कॉन्फ़िगर कर सकती हैं, जिससे समर्थित कन्वर्जन-नियम परिवर्तन ऐप स्टोर कनेक्ट पर एप्लिकेशन बाइनरी को दोबारा सबमिट किए बिना प्रभावी हो जाते हैं।

एप्लिकेशन-स्तरीय डीप-लिंक रूटिंग एक अलग माप और ऑनबोर्डिंग लेयर के रूप में Apple के गोपनीयता-संरक्षित एट्रिब्यूशन फ़्रेमवर्क के साथ काम कर सकती है। Openinstall जैसे प्लेटफ़ॉर्म प्रथम-पक्ष प्रासंगिक रूटिंग और डीफ़र्ड डीप लिंकिंग के लिए बुनियादी ढांचा प्रदान करते हैं, जिससे टीमों को वेब-से-ऐप कन्वर्जन फ़नल में उपयोगकर्ता के इरादे को संरक्षित करने की अनुमति मिलती है।

गोपनीयता-अनुरूप एट्रिब्यूशन और डीप लिंकिंग पाइपलाइन को कॉन्फ़िगर करने के बारे में अधिक जानने के लिए, Openinstall दस्तावेज़ की समीक्षा करें।

संबंधित सामग्रियां

  • अवधारणाएं: कन्वर्जन वैल्यू स्कीमा, डायनेमिक स्कीमा मैपिंग, रेवेन्यू बकेटिंग, विंडो लॉकिंग, मोनोरोनिसिटी

  • प्रौद्योगिकियां: Apple SKAdNetwork, Apple AdAttributionKit, StoreKit Framework, Openinstall Mobile SDK

  • मानक: IETF RFC 8259 JSON विनिर्देश

  • API: StoreKit updatePostbackConversionValue API, AdAttributionKit Postback.updateConversionValue API

आधिकारिक दस्तावेज़

Share this article

Keep Discovering

OpenAI क्या भारत में ChatGPT विज्ञापन ला रहा है? ऐप मार्केटिंग के लिए इसके क्या मायने हैं

OpenAI क्या भारत में ChatGPT विज्ञापन ला रहा है? ऐप मार्केटिंग के लिए इसके क्या मायने हैं

OpenAI ने भारत में फ्री और गो टियर पर ChatGPT विज्ञापन शुरू किए हैं। जानें कि संवादात्मक AI विज्ञापन मोबाइल ऐप मार्केटिंग और डिफर्ड डीप लिंकिंग को कैसे प्रभावित करते हैं।

Google ने पेश किया 4K जेमिनी ओम्नी (Gemini Omni)? वीडियो विज्ञापनों के लिए क्या बदल रहा है

Google ने पेश किया 4K जेमिनी ओम्नी (Gemini Omni)? वीडियो विज्ञापनों के लिए क्या बदल रहा है

Google ने 40-सेकंड के दृश्यों के साथ 4K जेमिनी ओम्नी पेश किया है। जानें कि स्केलेबल एआई वीडियो निर्माण अभियान मापन और मल्टी-टच एट्रिब्यूशन को कैसे प्रभावित करता है।

मोबाइल ऐप एनालिटिक्स उपयोगकर्ता रिटेंशन को कैसे ट्रैक और बेहतर बना सकते हैं

मोबाइल ऐप एनालिटिक्स उपयोगकर्ता रिटेंशन को कैसे ट्रैक और बेहतर बना सकते हैं

जानें कि मोबाइल ऐप एनालिटिक्स उपयोगकर्ताओं को समूहों (कोहॉर्ट्स) में विभाजित करके, सक्रिय-स्थिति के मानदंड निर्धारित करके और अनुभवजन्य रिटेंशन गिरावट का मॉडल तैयार करके उपयोगकर्ता रिटेंशन को कैसे ट्रैक करता है।