{"id":"93172b0c-a813-4f6c-b4fa-78269eec1403","shortId":"TpVdCC","kind":"skill","title":"adattributionkit","tagline":"Measure ad effectiveness with privacy-preserving attribution using AdAttributionKit. Use when registering ad impressions, handling attribution postbacks, updating conversion values, implementing re-engagement attribution, configuring publisher or advertiser apps, or replacing SKA","description":"# AdAttributionKit\n\nPrivacy-preserving ad attribution for iOS 17.4+ / Swift 6.3. AdAttributionKit\nlets ad networks measure conversions (installs and re-engagements) without\nexposing user-level data. It supports the App Store and alternative\nmarketplaces, and interoperates with SKAdNetwork.\n\nThree roles exist in the attribution flow: the **ad network** (signs\nimpressions, receives postbacks), the **publisher app** (displays ads), and the\n**advertised app** (the app being promoted).\n\n## Contents\n\n- [Overview and Privacy Model](#overview-and-privacy-model)\n- [Publisher App Setup](#publisher-app-setup)\n- [Advertiser App Setup](#advertiser-app-setup)\n- [Impressions](#impressions)\n- [Postbacks](#postbacks)\n- [Conversion Values](#conversion-values)\n- [Re-engagement](#re-engagement)\n- [Common Mistakes](#common-mistakes)\n- [Review Checklist](#review-checklist)\n- [References](#references)\n\n## Overview and Privacy Model\n\nAdAttributionKit preserves user privacy through several mechanisms:\n\n- **Crowd anonymity tiers** -- the device limits postback data granularity based\n  on the crowd size associated with the ad, ranging from Tier 0 (minimal data)\n  to Tier 3 (most data including publisher ID and country code).\n- **Time-delayed postbacks** -- postbacks are sent 24-48 hours after conversion\n  window close (first window) or 24-144 hours (second/third windows).\n- **No user-level identifiers** -- postbacks contain aggregate source\n  identifiers and conversion values, not device or user IDs.\n- **Hierarchical source identifiers** -- 2, 3, or 4-digit source IDs where the\n  number of digits returned depends on the crowd anonymity tier.\n\nThe system evaluates impressions from both AdAttributionKit and SKAdNetwork\ntogether when determining attribution winners. Only one impression wins per\nconversion. Click-through ads always take precedence over view-through ads,\nwith recency as the tiebreaker within each group.\n\n## Publisher App Setup\n\nA publisher app displays ads from registered ad networks. Add each ad network's\nID to the app's Info.plist so its impressions qualify for install validation.\n\n### Add ad network identifiers\n\n```xml\n<key>AdNetworkIdentifiers</key>\n<array>\n    <string>example123.adattributionkit</string>\n    <string>another456.adattributionkit</string>\n</array>\n```\n\nAd network IDs must be lowercase. SKAdNetwork IDs (ending in `.skadnetwork`)\nare also accepted -- the frameworks share IDs.\n\n### Display a UIEventAttributionView\n\nFor click-through custom-rendered ads, overlay a `UIEventAttributionView` on\nthe ad content. The system requires a tap on this view before `handleTap()`\nsucceeds.\n\n```swift\nimport UIKit\n\nlet attributionView = UIEventAttributionView()\nattributionView.frame = adContentView.bounds\nattributionView.isUserInteractionEnabled = true\nadContentView.addSubview(attributionView)\n```\n\n## Advertiser App Setup\n\nThe advertised app is the app someone installs or re-engages with after seeing\nan ad. It must call a conversion value update at least once to begin the\npostback conversion window.\n\n### Opt in to receive winning postback copies\n\nAdd the `AttributionCopyEndpoint` key to Info.plist so the device sends a copy\nof the winning postback to your server:\n\n```xml\n<key>AdAttributionKit</key>\n<dict>\n    <key>AttributionCopyEndpoint</key>\n    <string>https://example.com</string>\n</dict>\n```\n\nThe system generates a well-known path from the domain:\n\n```\nhttps://example.com/.well-known/appattribution/report-attribution/\n```\n\nConfigure your server to accept HTTPS POST requests at that path. The domain\nmust have a valid SSL certificate.\n\n### Opt in for re-engagement postback copies\n\nAdd a second key to also receive copies of winning re-engagement postbacks:\n\n```xml\n<key>AdAttributionKit</key>\n<dict>\n    <key>AttributionCopyEndpoint</key>\n    <string>https://example.com</string>\n    <key>OptInForReengagementPostbackCopies</key>\n    <true/>\n</dict>\n```\n\n### Update conversion value on first launch\n\nCall a conversion value update as early as possible after first launch to begin\nthe conversion window:\n\n```swift\nimport AdAttributionKit\n\nfunc applicationDidFinishLaunching() async {\n    do {\n        try await Postback.updateConversionValue(0, lockPostback: false)\n    } catch {\n        print(\"Failed to set initial conversion value: \\(error)\")\n    }\n}\n```\n\n## Impressions\n\nAd networks create signed impressions using JWS (JSON Web Signature). The\npublisher app uses `AppImpression` to register and handle those impressions.\n\n### Create an impression from a JWS\n\n```swift\nimport AdAttributionKit\n\nlet impression = try await AppImpression(compactJWS: signedJWSString)\n```\n\nThe JWS contains the ad network ID, advertised item ID, publisher item ID,\nsource identifier, timestamp, and optional re-engagement eligibility flag. See\n[references/adattributionkit-patterns.md](references/adattributionkit-patterns.md)\nfor JWS generation details.\n\n### Check device support\n\n```swift\nguard AppImpression.isSupported else {\n    // Fall back to alternative ad display\n    return\n}\n```\n\n### View-through impressions\n\nRecord a view impression when the ad content has been displayed and dismissed:\n\n```swift\nfunc handleAdViewed(impression: AppImpression) async {\n    do {\n        try await impression.handleView()\n    } catch {\n        print(\"Failed to record view-through impression: \\(error)\")\n    }\n}\n```\n\nFor long-lived ad views, use `beginView()` and `endView()` to track view\nduration:\n\n```swift\ntry await impression.beginView()\n// ... ad remains visible ...\ntry await impression.endView()\n```\n\n### Click-through impressions\n\nRespond to ad taps by calling `handleTap()`. If the advertised app is not\ninstalled, the system opens its App Store or marketplace page. If installed,\nthe system launches it directly.\n\n```swift\nfunc handleAdTapped(impression: AppImpression) async {\n    do {\n        try await impression.handleTap()\n    } catch {\n        print(\"Failed to record click-through impression: \\(error)\")\n    }\n}\n```\n\nA `UIEventAttributionView` must overlay the ad for `handleTap()` to succeed.\n\n### StoreKit-rendered ads\n\nPass the impression to StoreKit overlay or product view controller APIs. StoreKit\nautomatically records view-through impressions after 2 seconds of display and\nclick-through impressions on tap.\n\n```swift\nimport StoreKit\n\nlet config = SKOverlay.AppConfiguration(appIdentifier: \"1234567890\",\n                                         position: .bottom)\nconfig.appImpression = impression\n```\n\n## Postbacks\n\nPostbacks are attribution reports the device sends to ad networks (and\noptionally to the advertised app developer) after a conversion event.\n\n### Conversion windows\n\nThree windows produce up to three postbacks for winning attributions:\n\n| Window | Duration            | Postback delay    |\n|--------|---------------------|-------------------|\n| 1st    | Days 0-2            | 24-48 hours       |\n| 2nd    | Days 3-7            | 24-144 hours      |\n| 3rd    | Days 8-35           | 24-144 hours      |\n\nTier 0 postbacks only produce the first postback. Nonwinning attributions\nproduce only one postback.\n\n### Time windows for events\n\n| Event                          | Time limit                              |\n|--------------------------------|-----------------------------------------|\n| View-through to install        | 24 hours (configurable up to 7 days)    |\n| Click-through to install       | 30 days (configurable down to 1 day)    |\n| Install to first update        | 60 days                                 |\n| Re-engagement to first update  | 2 days                                  |\n\n### Lock conversion values early\n\nLock the postback to finalize a conversion value before the window ends and\nreceive the postback sooner:\n\n```swift\ntry await Postback.updateConversionValue(\n    42,\n    coarseConversionValue: .high,\n    lockPostback: true\n)\n```\n\nAfter locking, the system ignores further updates in that conversion window.\n\n### Postback data by tier\n\n| Field                        | Tier 0 | Tier 1      | Tier 2      | Tier 3      |\n|------------------------------|--------|-------------|-------------|-------------|\n| `source-identifier` digits   | 2      | 2           | 2-4         | 2-4         |\n| `conversion-value` (fine)    | --     | --          | 1st only    | 1st only    |\n| `coarse-conversion-value`    | --     | 1st only    | 2nd/3rd     | 2nd/3rd     |\n| `publisher-item-identifier`  | --     | --          | --          | Yes         |\n| `country-code`               | --     | --          | --          | Conditional |\n\n## Conversion Values\n\n### Fine-grained values\n\nAn integer from 0-63 (6 bits). Available only in the first postback and only at\nTier 2 or higher:\n\n```swift\ntry await Postback.updateConversionValue(\n    35,\n    coarseConversionValue: .medium,\n    lockPostback: false\n)\n```\n\n### Coarse values\n\nThree levels for lower tiers and second/third postbacks:\n\n```swift\n// CoarseConversionValue cases: .low, .medium, .high\ntry await Postback.updateConversionValue(\n    10,\n    coarseConversionValue: .high,\n    lockPostback: false\n)\n```\n\n### Update by conversion type (iOS 18+)\n\nSeparate conversion values for install vs. re-engagement postbacks:\n\n```swift\nlet installUpdate = PostbackUpdate(\n    fineConversionValue: 20,\n    lockPostback: false,\n    conversionTypes: [.install]\n)\ntry await Postback.updateConversionValue(installUpdate)\n\nlet reengagementUpdate = PostbackUpdate(\n    fineConversionValue: 12,\n    lockPostback: false,\n    conversionTypes: [.reengagement]\n)\ntry await Postback.updateConversionValue(reengagementUpdate)\n```\n\n### Conversion tags (iOS 18.4+)\n\nUse conversion tags to selectively update specific postbacks when overlapping\nconversion windows exist:\n\n```swift\nlet update = PostbackUpdate(\n    fineConversionValue: 15,\n    lockPostback: false,\n    conversionTag: savedConversionTag,\n    conversionTypes: [.reengagement]\n)\ntry await Postback.updateConversionValue(update)\n```\n\nThe system delivers the conversion tag through the re-engagement URL's\n`AdAttributionKitReengagementOpen` query parameter.\n\n## Re-engagement\n\nRe-engagement tracks users who already have the advertised app installed and\ninteract with an ad to return to it.\n\n### Mark impressions as re-engagement eligible\n\nSet `eligible-for-re-engagement` to `true` in the JWS payload when generating\nthe impression.\n\n### Handle re-engagement taps with a URL\n\nPass a universal link that the system opens in the advertised app:\n\n```swift\nlet reengagementURL = URL(string: \"https://example.com/promo/summer\")!\ntry await impression.handleTap(reengagementURL: reengagementURL)\n```\n\nThe system appends `AdAttributionKitReengagementOpen` as a query parameter. The\nadvertised app checks for this parameter to detect AdAttributionKit-driven\nopens:\n\n```swift\nfunc handleUniversalLink(_ url: URL) {\n    let components = URLComponents(url: url, resolvingAgainstBaseURL: false)\n    let isReengagement = components?.queryItems?.contains(where: {\n        $0.name == Postback.reengagementOpenURLParameter\n    }) ?? false\n\n    if isReengagement {\n        // AdAttributionKit opened this app via a re-engagement ad\n    }\n}\n```\n\n### Re-engagement limits\n\n- Only click-through interactions create re-engagement postbacks (not\n  view-through).\n- The device enforces monthly per-app and yearly per-device re-engagement\n  limits.\n- The `AdAttributionKitReengagementOpen` parameter is always present on the\n  URL, even when the system does not create a postback.\n\n## Common Mistakes\n\n### Forgetting to update conversion value on launch\n\n```swift\n// DON'T -- never updating the conversion value\nfunc appDidLaunch() {\n    // No conversion value update; postback window never starts\n}\n\n// DO -- update conversion value on first launch\nfunc appDidLaunch() async {\n    try? await Postback.updateConversionValue(0, lockPostback: false)\n}\n```\n\n### Using uppercase ad network IDs\n\n```xml\n<!-- DON'T -->\n<string>Example123.AdAttributionKit</string>\n\n<!-- DO -->\n<string>example123.adattributionkit</string>\n```\n\n### Calling handleTap without UIEventAttributionView\n\n```swift\n// DON'T -- tap without attribution view overlay\ntry await impression.handleTap()\n// Throws AdAttributionKitError.missingAttributionView\n\n// DO -- ensure UIEventAttributionView covers the ad\nlet attributionView = UIEventAttributionView()\nattributionView.frame = adView.bounds\nadView.addSubview(attributionView)\n// Then handle the tap after the user taps the attribution view\ntry await impression.handleTap()\n```\n\n### Ignoring handleTap errors\n\n```swift\n// DON'T\ntry? await impression.handleTap()\n\n// DO -- handle specific errors\ndo {\n    try await impression.handleTap()\n} catch let error as AdAttributionKitError {\n    switch error {\n    case .impressionExpired:\n        // Impression older than 30 days\n        refreshAdImpression()\n    case .missingAttributionView:\n        // UIEventAttributionView not present\n        break\n    default:\n        print(\"Attribution error: \\(error)\")\n    }\n}\n```\n\n### Not responding to postback requests\n\n```swift\n// DON'T -- silently dropping the request\n// The device retries up to 9 times over 9 days on HTTP 500\n\n// DO -- respond with 200 OK immediately\n// Server handler:\nfunc handlePostback(request: Request) -> Response {\n    // Process asynchronously, respond immediately\n    Task { await processPostback(request.body) }\n    return Response(status: .ok)\n}\n```\n\n## Review Checklist\n\n- [ ] Publisher app includes all ad network IDs in `AdNetworkIdentifiers`\n  (lowercase)\n- [ ] Ad network IDs match between publisher app's Info.plist and JWS `kid`\n- [ ] `UIEventAttributionView` overlays ad content for click-through ads\n- [ ] Advertised app calls `updateConversionValue` on first launch\n- [ ] Server endpoint at well-known path accepts HTTPS POST with valid SSL\n- [ ] Postback verification uses correct Apple public key for environment\n- [ ] Duplicate postbacks filtered by `postback-identifier`\n- [ ] Server responds with HTTP 200 to postback requests\n- [ ] Re-engagement URL is a registered universal link for the advertised app\n- [ ] Conversion value strategy accounts for all three conversion windows\n- [ ] `AppImpression.isSupported` checked before attempting impression APIs\n\n## References\n\n- [references/adattributionkit-patterns.md](references/adattributionkit-patterns.md)\n  -- postback verification, server handling, testing, SKAdNetwork migration,\n  alternative marketplaces, attribution rules configuration\n- [Apple: AdAttributionKit](https://sosumi.ai/documentation/adattributionkit)\n- [Apple: Presenting ads in your app](https://sosumi.ai/documentation/adattributionkit/presenting-ads-in-your-app)\n- [Apple: Receiving ad attributions and postbacks](https://sosumi.ai/documentation/adattributionkit/receiving-ad-attributions-and-postbacks)\n- [Apple: Verifying a postback](https://sosumi.ai/documentation/adattributionkit/verifying-a-postback)\n- [Apple: SKAdNetwork interoperability](https://sosumi.ai/documentation/adattributionkit/adattributionkit-skadnetwork-interoperability)","tags":["adattributionkit","swift","ios","skills","dpearson2699","accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills"],"capabilities":["skill","source-dpearson2699","skill-adattributionkit","topic-accessibility","topic-agent-skills","topic-ai-coding","topic-apple","topic-claude-code","topic-codex-skills","topic-cursor-skills","topic-ios","topic-ios-development","topic-liquid-glass","topic-localization","topic-mapkit"],"categories":["swift-ios-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/dpearson2699/swift-ios-skills/adattributionkit","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add dpearson2699/swift-ios-skills","source_repo":"https://github.com/dpearson2699/swift-ios-skills","install_from":"skills.sh"}},"qualityScore":"0.684","qualityRationale":"deterministic score 0.68 from registry signals: · indexed on github topic:agent-skills · 468 github stars · SKILL.md body (14,973 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T00:53:41.063Z","embedding":null,"createdAt":"2026-04-18T22:00:40.011Z","updatedAt":"2026-04-22T00:53:41.063Z","lastSeenAt":"2026-04-22T00:53:41.063Z","tsv":"'-144':218,873,880 '-2':864 '-35':878 '-4':1002,1004 '-48':208,866 '-63':1040 '-7':871 '/.well-known/appattribution/report-attribution/':478 '/documentation/adattributionkit)':1679 '/documentation/adattributionkit/adattributionkit-skadnetwork-interoperability)':1710 '/documentation/adattributionkit/presenting-ads-in-your-app)':1688 '/documentation/adattributionkit/receiving-ad-attributions-and-postbacks)':1697 '/documentation/adattributionkit/verifying-a-postback)':1704 '/promo/summer':1255 '0':186,558,863,883,988,1039,1407 '0.name':1300 '1':925,990 '10':1084 '12':1123 '1234567890':818 '15':1154 '17.4':44 '18':1094 '18.4':1135 '1st':861,1009,1011,1017 '2':243,800,939,992,999,1000,1001,1003,1053 '20':1110 '200':1533,1628 '24':207,217,865,872,879,908 '2nd':868 '2nd/3rd':1019,1020 '3':191,244,870,994 '30':920,1491 '35':1060 '3rd':875 '4':246 '42':966 '500':1529 '6':1041 '6.3':46 '60':931 '7':913 '8':877 '9':1522,1525 'accept':353,483,1602 'account':1648 'ad':3,15,40,49,84,94,182,285,293,309,312,316,333,340,368,374,418,571,612,649,662,693,707,719,772,780,832,1200,1314,1412,1440,1561,1567,1581,1587,1682,1691 'adattributionkit':1,11,36,47,158,268,462,521,550,600,1279,1305,1676 'adattributionkit-driven':1278 'adattributionkiterror':1483 'adattributionkiterror.missingattributionview':1434 'adattributionkitreengagementopen':1178,1264,1350 'adcontentview.addsubview':397 'adcontentview.bounds':394 'add':314,332,442,506 'adnetworkidentifi':337,1565 'advertis':31,97,120,124,399,403,615,726,838,1193,1246,1270,1588,1643 'advertiser-app-setup':123 'adview.addsubview':1446 'adview.bounds':1445 'aggreg':229 'alreadi':1190 'also':352,511 'altern':70,648,1670 'alway':286,1353 'anonym':166,260 'another456.adattributionkit':339 'api':791,1659 'app':32,67,92,98,100,114,118,121,125,303,307,322,400,404,407,583,727,735,839,1194,1247,1271,1308,1339,1558,1573,1589,1644,1685 'appdidlaunch':1385,1402 'append':1263 'appidentifi':817 'appimpress':585,605,673,751 'appimpression.issupported':643,1654 'appl':1612,1675,1680,1689,1698,1705 'applicationdidfinishlaunch':552 'associ':179 'async':553,674,752,1403 'asynchron':1544 'attempt':1657 'attribut':9,18,27,41,81,274,826,856,891,1427,1457,1502,1672,1692 'attributioncopyendpoint':444,463,522 'attributionview':391,398,1442,1447 'attributionview.frame':393,1444 'attributionview.isuserinteractionenabled':395 'automat':793 'avail':1043 'await':556,604,677,705,711,755,964,1058,1082,1116,1129,1162,1257,1405,1431,1460,1469,1477,1548 'back':646 'base':174 'begin':430,544 'beginview':696 'bit':1042 'bottom':820 'break':1499 'call':421,531,722,1418,1590 'case':1077,1486,1494 'catch':561,679,757,1479 'certif':497 'check':638,1272,1655 'checklist':148,151,1556 'click':283,363,714,763,806,916,1321,1585 'click-through':282,362,713,762,805,915,1320,1584 'close':213 'coars':1014,1065 'coarse-conversion-valu':1013 'coarseconversionvalu':967,1061,1076,1085 'code':199,1028 'common':142,145,1367 'common-mistak':144 'compactjw':606 'compon':1288,1296 'condit':1029 'config':815 'config.appimpression':821 'configur':28,479,910,922,1674 'contain':228,610,1298 'content':103,375,663,1582 'control':790 'convers':21,52,131,134,211,233,281,423,433,526,533,546,567,843,845,942,951,980,1006,1015,1030,1091,1096,1132,1137,1146,1169,1372,1382,1387,1396,1645,1652 'conversion-valu':133,1005 'conversiontag':1157 'conversiontyp':1113,1126,1159 'copi':441,453,505,513 'correct':1611 'countri':198,1027 'country-cod':1026 'cover':1438 'creat':573,592,1324,1364 'crowd':165,177,259 'custom':366 'custom-rend':365 'data':63,172,188,193,983 'day':862,869,876,914,921,926,932,940,1492,1526 'default':1500 'delay':202,860 'deliv':1167 'depend':256 'detail':637 'detect':1277 'determin':273 'develop':840 'devic':169,236,450,639,829,1334,1344,1518 'digit':247,254,998 'direct':746 'dismiss':668 'display':93,308,358,650,666,803 'domain':475,491 'driven':1280 'drop':1514 'duplic':1617 'durat':702,858 'earli':537,944 'effect':4 'elig':629,1211,1214 'eligible-for-re-engag':1213 'els':644 'end':348,956 'endpoint':1596 'endview':698 'enforc':1335 'engag':26,57,138,141,413,503,518,628,935,1103,1175,1183,1186,1210,1217,1231,1313,1317,1327,1347,1634 'ensur':1436 'environ':1616 'error':569,688,766,1464,1474,1481,1485,1503,1504 'evalu':264 'even':1358 'event':844,899,900 'example.com':464,477,523,1254 'example.com/.well-known/appattribution/report-attribution/':476 'example.com/promo/summer':1253 'example123.adattributionkit':338,1416,1417 'exist':78,1148 'expos':59 'fail':563,681,759 'fall':645 'fals':560,1064,1088,1112,1125,1156,1293,1302,1409 'field':986 'filter':1619 'final':949 'fine':1008,1033 'fine-grain':1032 'fineconversionvalu':1109,1122,1153 'first':214,529,541,888,929,937,1047,1399,1593 'flag':630 'flow':82 'forget':1369 'framework':355 'func':551,670,748,1283,1384,1401,1538 'generat':467,636,1225 'grain':1034 'granular':173 'group':301 'guard':642 'handl':17,589,1228,1449,1472,1666 'handleadtap':749 'handleadview':671 'handlepostback':1539 'handler':1537 'handletap':385,723,774,1419,1463 'handleuniversallink':1284 'hierarch':240 'high':968,1080,1086 'higher':1055 'hour':209,219,867,874,881,909 'http':1528,1627 'https':484,1603 'id':196,239,249,319,342,347,357,614,617,620,1414,1563,1569 'identifi':226,231,242,335,622,997,1024,1623 'ignor':975,1462 'immedi':1535,1546 'implement':23 'import':388,549,599,812 'impress':16,87,127,128,265,278,327,570,575,591,594,602,655,659,672,687,716,750,765,783,798,808,822,1206,1227,1488,1658 'impression.beginview':706 'impression.endview':712 'impression.handletap':756,1258,1432,1461,1470,1478 'impression.handleview':678 'impressionexpir':1487 'includ':194,1559 'info.plist':324,447,1575 'initi':566 'instal':53,330,409,730,741,907,919,927,1099,1114,1195 'installupd':1107,1118 'integ':1037 'interact':1197,1323 'interoper':73,1707 'io':43,1093,1134 'isreengag':1295,1304 'item':616,619,1023 'json':578 'jws':577,597,609,635,1222,1577 'key':445,509,1614 'kid':1578 'known':471,1600 'launch':530,542,744,1375,1400,1594 'least':427 'let':48,390,601,814,1106,1119,1150,1249,1287,1294,1441,1480 'level':62,225,1068 'limit':170,902,1318,1348 'link':1239,1640 'live':692 'lock':941,945,972 'lockpostback':559,969,1063,1087,1111,1124,1155,1408 'long':691 'long-liv':690 'low':1078 'lower':1070 'lowercas':345,1566 'mark':1205 'marketplac':71,738,1671 'match':1570 'measur':2,51 'mechan':164 'medium':1062,1079 'migrat':1669 'minim':187 'missingattributionview':1495 'mistak':143,146,1368 'model':107,112,157 'month':1336 'must':343,420,492,769 'network':50,85,313,317,334,341,572,613,833,1413,1562,1568 'never':1379,1392 'nonwin':890 'number':252 'ok':1534,1554 'older':1489 'one':277,894 'open':733,1243,1281,1306 'opt':435,498 'optinforreengagementpostbackcopi':524 'option':625,835 'overlap':1145 'overlay':369,770,786,1429,1580 'overview':104,109,154 'overview-and-privacy-model':108 'page':739 'paramet':1180,1268,1275,1351 'pass':781,1236 'path':472,489,1601 'payload':1223 'per':280,1338,1343 'per-app':1337 'per-devic':1342 'posit':819 'possibl':539 'post':485,1604 'postback':19,89,129,130,171,203,204,227,432,440,457,504,519,823,824,853,859,884,889,895,947,960,982,1048,1074,1104,1143,1328,1366,1390,1508,1608,1618,1622,1630,1663,1694,1701 'postback-identifi':1621 'postback.reengagementopenurlparameter':1301 'postback.updateconversionvalue':557,965,1059,1083,1117,1130,1163,1406 'postbackupd':1108,1121,1152 'preced':288 'present':1354,1498,1681 'preserv':8,39,159 'print':562,680,758,1501 'privaci':7,38,106,111,156,161 'privacy-preserv':6,37 'process':1543 'processpostback':1549 'produc':849,886,892 'product':788 'promot':102 'public':1613 'publish':29,91,113,117,195,302,306,582,618,1022,1557,1572 'publisher-app-setup':116 'publisher-item-identifi':1021 'qualifi':328 'queri':1179,1267 'queryitem':1297 'rang':183 're':25,56,137,140,412,502,517,627,934,1102,1174,1182,1185,1209,1216,1230,1312,1316,1326,1346,1633 're-engag':24,55,136,139,411,501,516,626,933,1101,1173,1181,1184,1208,1229,1311,1315,1325,1345,1632 'receiv':88,438,512,958,1690 'recenc':295 'record':656,683,761,794 'reengag':1127,1160 'reengagementupd':1120,1131 'reengagementurl':1250,1259,1260 'refer':152,153,1660 'references/adattributionkit-patterns.md':632,633,1661,1662 'refreshadimpress':1493 'regist':14,311,587,1638 'remain':708 'render':367,779 'replac':34 'report':827 'request':486,1509,1516,1540,1541,1631 'request.body':1550 'requir':378 'resolvingagainstbaseurl':1292 'respond':717,1506,1531,1545,1625 'respons':1542,1552 'retri':1519 'return':255,651,1202,1551 'review':147,150,1555 'review-checklist':149 'role':77 'rule':1673 'savedconversiontag':1158 'second':508,801 'second/third':220,1073 'see':416,631 'select':1140 'send':451,830 'sent':206 'separ':1095 'server':460,481,1536,1595,1624,1665 'set':565,1212 'setup':115,119,122,126,304,401 'sever':163 'share':356 'sign':86,574 'signatur':580 'signedjwsstr':607 'silent':1513 'size':178 'ska':35 'skadnetwork':75,270,346,350,1668,1706 'skill' 'skill-adattributionkit' 'skoverlay.appconfiguration':816 'someon':408 'sooner':961 'sosumi.ai':1678,1687,1696,1703,1709 'sosumi.ai/documentation/adattributionkit)':1677 'sosumi.ai/documentation/adattributionkit/adattributionkit-skadnetwork-interoperability)':1708 'sosumi.ai/documentation/adattributionkit/presenting-ads-in-your-app)':1686 'sosumi.ai/documentation/adattributionkit/receiving-ad-attributions-and-postbacks)':1695 'sosumi.ai/documentation/adattributionkit/verifying-a-postback)':1702 'sourc':230,241,248,621,996 'source-dpearson2699' 'source-identifi':995 'specif':1142,1473 'ssl':496,1607 'start':1393 'status':1553 'store':68,736 'storekit':778,785,792,813 'storekit-rend':777 'strategi':1647 'string':1252 'succeed':386,776 'support':65,640 'swift':45,387,548,598,641,669,703,747,811,962,1056,1075,1105,1149,1248,1282,1376,1422,1465,1510 'switch':1484 'system':263,377,466,732,743,974,1166,1242,1262,1361 'tag':1133,1138,1170 'take':287 'tap':380,720,810,1232,1425,1451,1455 'task':1547 'test':1667 'three':76,847,852,1067,1651 'throw':1433 'tiebreak':298 'tier':167,185,190,261,882,985,987,989,991,993,1052,1071 'time':201,896,901,1523 'time-delay':200 'timestamp':623 'togeth':271 'topic-accessibility' 'topic-agent-skills' 'topic-ai-coding' 'topic-apple' 'topic-claude-code' 'topic-codex-skills' 'topic-cursor-skills' 'topic-ios' 'topic-ios-development' 'topic-liquid-glass' 'topic-localization' 'topic-mapkit' 'track':700,1187 'tri':555,603,676,704,710,754,963,1057,1081,1115,1128,1161,1256,1404,1430,1459,1468,1476 'true':396,970,1219 'type':1092 'uieventattributionview':360,371,392,768,1421,1437,1443,1496,1579 'uikit':389 'univers':1238,1639 'updat':20,425,525,535,930,938,977,1089,1141,1151,1164,1371,1380,1389,1395 'updateconversionvalu':1591 'uppercas':1411 'url':1176,1235,1251,1285,1286,1290,1291,1357,1635 'urlcompon':1289 'use':10,12,576,584,695,1136,1410,1610 'user':61,160,224,238,1188,1454 'user-level':60,223 'valid':331,495,1606 'valu':22,132,135,234,424,527,534,568,943,952,1007,1016,1031,1035,1066,1097,1373,1383,1388,1397,1646 'verif':1609,1664 'verifi':1699 'via':1309 'view':291,383,653,658,685,694,701,789,796,904,1331,1428,1458 'view-through':290,652,684,795,903,1330 'visibl':709 'vs':1100 'web':579 'well':470,1599 'well-known':469,1598 'win':279,439,456,515,855 'window':212,215,221,434,547,846,848,857,897,955,981,1147,1391,1653 'winner':275 'within':299 'without':58,1420,1426 'xml':336,461,520,1415 'year':1341 'yes':1025","prices":[{"id":"3fe9b026-69db-4e21-8df3-ace36835042d","listingId":"93172b0c-a813-4f6c-b4fa-78269eec1403","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"dpearson2699","category":"swift-ios-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:00:40.011Z"}],"sources":[{"listingId":"93172b0c-a813-4f6c-b4fa-78269eec1403","source":"github","sourceId":"dpearson2699/swift-ios-skills/adattributionkit","sourceUrl":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/adattributionkit","isPrimary":false,"firstSeenAt":"2026-04-18T22:00:40.011Z","lastSeenAt":"2026-04-22T00:53:41.063Z"}],"details":{"listingId":"93172b0c-a813-4f6c-b4fa-78269eec1403","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"dpearson2699","slug":"adattributionkit","github":{"repo":"dpearson2699/swift-ios-skills","stars":468,"topics":["accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills","ios","ios-development","liquid-glass","localization","mapkit","networking","storekit","swift","swift-concurrency","swiftdata","swiftui","widgetkit","xcode"],"license":"other","html_url":"https://github.com/dpearson2699/swift-ios-skills","pushed_at":"2026-04-21T19:26:16Z","description":"Agent Skills for iOS 26+, Swift 6.3, SwiftUI, and modern Apple frameworks","skill_md_sha":"b5016b934cce2da0cea67962c0c0d98246ebb691","skill_md_path":"skills/adattributionkit/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/adattributionkit"},"layout":"multi","source":"github","category":"swift-ios-skills","frontmatter":{"name":"adattributionkit","description":"Measure ad effectiveness with privacy-preserving attribution using AdAttributionKit. Use when registering ad impressions, handling attribution postbacks, updating conversion values, implementing re-engagement attribution, configuring publisher or advertiser apps, or replacing SKAdNetwork with AdAttributionKit for ad measurement."},"skills_sh_url":"https://skills.sh/dpearson2699/swift-ios-skills/adattributionkit"},"updatedAt":"2026-04-22T00:53:41.063Z"}}