{"_id":"@afrokala/ads-sdk","name":"@afrokala/ads-sdk","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@afrokala/ads-sdk","version":"0.1.0","description":"Afrokala Ads SDK — core + vanilla client. Transport, caching, event outbox, DOM renderers for banner/interstitial/inline/rewarded ad units.","license":"UNLICENSED","repository":{"type":"git","url":"git+https://github.com/kumbiraibenjamin/afrokala-ads-sdk.git","directory":"packages/ads-sdk"},"type":"module","sideEffects":false,"engines":{"node":">=18"},"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","unpkg":"./dist/ads-sdk.global.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"publishConfig":{"access":"public","provenance":false},"dependencies":{"zod":"^3.24.1"},"devDependencies":{"@arethetypeswrong/cli":"^0.18.5","eslint":"^9.17.0","jsdom":"^25.0.1","publint":"^0.3.22","tsup":"^8.3.5","typescript":"^5.7.2","vitest":"^2.1.8","@afrokala/config":"0.0.0"},"scripts":{"build":"tsup","dev":"tsup --watch","lint":"eslint .","typecheck":"tsc --noEmit","test":"vitest run","check:contract-drift":"node scripts/check-contract-drift.mjs","check:pkg-hygiene":"publint && attw --pack .","check:bundle-size":"node scripts/check-bundle-size.mjs"},"_id":"@afrokala/ads-sdk@0.1.0","bugs":{"url":"https://github.com/kumbiraibenjamin/afrokala-ads-sdk/issues"},"homepage":"https://github.com/kumbiraibenjamin/afrokala-ads-sdk#readme","_integrity":"sha512-tbK9aid8YxHxeFfyTrgBquRPd6CQ0sHoatFBFJoNA6eXUSvVlgxyzN+Rid4H5yIkqEByJNNHRUnd9V/KpJVUUA==","_resolved":"C:\\Users\\kbdev\\AppData\\Local\\Temp\\f1f360eee1f18b5c028e653c1bcebaf4\\afrokala-ads-sdk-0.1.0.tgz","_from":"file:afrokala-ads-sdk-0.1.0.tgz","_nodeVersion":"22.13.1","_npmVersion":"11.4.1","dist":{"integrity":"sha512-tbK9aid8YxHxeFfyTrgBquRPd6CQ0sHoatFBFJoNA6eXUSvVlgxyzN+Rid4H5yIkqEByJNNHRUnd9V/KpJVUUA==","shasum":"3abb3089b51174141a9f46ecad8d67729f3b10e2","tarball":"https://registry.npmjs.org/@afrokala/ads-sdk/-/ads-sdk-0.1.0.tgz","fileCount":10,"unpackedSize":1008773,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDdwN7EGvEFUKHUmebinDbRZMqm00xzULd7wjP3K/fBOAIgUydycHjafLGVgP38pzZPgUz2jSC3ZWGv6P3TPK1QX0k="}]},"_npmUser":{"name":"kumbiraibenjamin","email":"kbdeve@gmail.com"},"directories":{},"maintainers":[{"name":"kumbiraibenjamin","email":"kbdeve@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ads-sdk_0.1.0_1785171383457_0.0020984899674758584"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-27T16:56:23.285Z","0.1.0":"2026-07-27T16:56:23.614Z","modified":"2026-07-27T16:56:23.828Z"},"maintainers":[{"name":"kumbiraibenjamin","email":"kbdeve@gmail.com"}],"description":"Afrokala Ads SDK — core + vanilla client. Transport, caching, event outbox, DOM renderers for banner/interstitial/inline/rewarded ad units.","homepage":"https://github.com/kumbiraibenjamin/afrokala-ads-sdk#readme","repository":{"type":"git","url":"git+https://github.com/kumbiraibenjamin/afrokala-ads-sdk.git","directory":"packages/ads-sdk"},"bugs":{"url":"https://github.com/kumbiraibenjamin/afrokala-ads-sdk/issues"},"license":"UNLICENSED","readme":"# @afrokala/ads-sdk\r\n\r\nCore + vanilla client for the Afrokala Ads network. Framework-free TypeScript: transport\r\n(`requestAd` fetch + retry/backoff), a serve-token store, prefetch + LRU cache with TTL, an event\r\noutbox (idempotency keys, batching ≤500, retry, `localStorage` persistence for offline), and DOM\r\nrenderers for all four ad unit types.\r\n\r\n> Status: core landed (sdk-002); CDN/IIFE auto-mount hardened (sdk-005). `AdsClient` implements the\r\n> anonymous-device transport (`requestAd` with timeout + bounded retry/backoff), a TTL/LRU decision\r\n> cache, the idempotent event outbox (`postClientAdEvents`, persisted, dedupe-by-serve), viewability\r\n> impression counting, and the four DOM renderers. Framework wrappers (React landed, Vue/Angular\r\n> follow in sdk-006/007).\r\n\r\n## Install\r\n\r\n```bash\r\npnpm add @afrokala/ads-sdk\r\n```\r\n\r\nOr via CDN — see **[docs/vanilla.md](../../docs/vanilla.md)** for the full vanilla/CDN quick-start\r\n(script tag attributes, ad-unit data attributes, manual init for SPA timing, bundle-size budget):\r\n\r\n```html\r\n<script src=\"https://unpkg.com/@afrokala/ads-sdk/dist/ads-sdk.global.js\" data-app-id=\"your-app-id\"></script>\r\n<div data-afk-unit=\"home_banner\"></div>\r\n```\r\n\r\n## Quick start\r\n\r\n```ts\r\nimport { AdsClient } from \"@afrokala/ads-sdk\";\r\n\r\nconst client = new AdsClient({\r\n  appId: \"your-app-id\",\r\n  endpoint: \"https://serve.afrokala.example\", // serving base (requestAd / postClientAdEvents)\r\n  onOpenUrl: (url) => window.open(url, \"_blank\", \"noopener\"),\r\n});\r\n\r\nclient.mountBanner(document.querySelector(\"#banner\")!, \"home_banner\");\r\nclient.mountInline(document.querySelector(\"#feed\")!, \"feed_slot\", { mode: \"block\" });\r\nawait client.showInterstitial(\"interstitial_unit\");\r\n\r\nconst rewarded = client.loadRewarded(\"rewarded_unit\");\r\nrewarded.onReward((meta) => {\r\n  // ADVISORY only — surface a \"reward pending\" UX. Server-Side Verification (SSV) is the sole\r\n  // authoritative grant path; never credit a user on onReward alone.\r\n});\r\n// when rewarded.state === \"loaded\", rewarded.serveId carries the exact serve's `serveId` claim\r\n// (null before load / after a no-fill) — an attribution HINT for binding a reward intent to this\r\n// serve, not proof: SSV remains the only money-grade signal.\r\nrewarded.show();\r\n```\r\n\r\n### Privacy + invariants\r\n\r\n- **No PII.** The only identifier is an anonymous, regenerable `deviceId` UUID kept in localStorage.\r\n- **An ad error never breaks the host app.** No-fill and network failure both resolve to a silent\r\n  no-ad; every host callback (`onError`/`onOpenUrl`/`onReward`/`onClose`) is invoked defensively.\r\n- **Rewards are advisory.** `onReward` fires on client-side completion as a UX hint; SSV (net-004) is\r\n  the only path that actually grants a reward.\r\n\r\n## Contracts\r\n\r\n`src/contracts/` holds the wire schemas (`getCampaignsForApp` response, `postAdEvents`\r\nrequest/response) **copied** from `afrokala/functions/src/serving/contract.ts` — the\r\ncontracts-not-code rule. `src/contracts/fixtures/` holds real emulator-shaped payloads;\r\n`src/contracts/contracts.test.ts` round-trips every fixture through its schema.\r\n\r\n`contract.lock.json` pins a sha256 hash of `primitives.ts` + `get-campaigns.ts` +\r\n`post-ad-events.ts`. `pnpm check:contract-drift` (wired into CI) recomputes the hash and fails the\r\nbuild if it no longer matches — catching an edit to the SDK's copy that wasn't first mirrored on\r\nthe afrokala side.\r\n\r\nTo deliberately re-pin after a real, mirrored contract change:\r\n\r\n```bash\r\npnpm --filter @afrokala/ads-sdk check:contract-drift -- --write\r\n```\r\n\r\n## Scripts\r\n\r\n| Script | What it does |\r\n|---|---|\r\n| `build` | `tsup` — emits ESM + CJS (`dist/index.{js,cjs}`) and an IIFE CDN bundle (`dist/ads-sdk.global.js`, from `src/cdn-entry.ts`) |\r\n| `test` | `vitest run` |\r\n| `typecheck` | `tsc --noEmit` |\r\n| `lint` | `eslint .` |\r\n| `check:contract-drift` | Hashes `src/contracts/*.ts` against `contract.lock.json` |\r\n| `check:bundle-size` | Gzips `dist/ads-sdk.global.js` and fails if it exceeds the 30 KiB budget |\r\n\r\n## Vanilla / CDN\r\n\r\n`src/index.ts` (ESM/CJS) stays side-effect-free; `src/cdn-entry.ts` is the separate, side-effecting\r\nentry tsup builds into the IIFE — it boots auto-mount on load and is what `window.AfrokalaAdsSDK`\r\nresolves to on the CDN build. `src/cdn.ts` holds the testable bootstrap logic (`init`/`boot`):\r\nauto-mount discovery, a `MutationObserver` for SPA-safe late-added slots, a multiple-`<script\r\ndata-app-id>`-tag guard, and an idempotent `init()` so a second call/tag never spins up a second\r\n`AdsClient`. Full quick-start: [`docs/vanilla.md`](../../docs/vanilla.md).\r\n","readmeFilename":"README.md","_rev":"1-0902c9413c6eede58548ddc2ca64f981"}