sovads-sdk 1.0.8 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,149 +1,285 @@
1
- # @sovads/sdk
1
+ # sovads-sdk
2
2
 
3
- SovAds SDK for publisher integration - A modular ad network SDK with banner, popup, and sidebar components.
3
+ [![npm version](https://img.shields.io/npm/v/sovads-sdk.svg)](https://www.npmjs.com/package/sovads-sdk)
4
+ [![license](https://img.shields.io/npm/l/sovads-sdk.svg)](https://github.com/sovseas/sovads/blob/main/sdk/LICENSE)
5
+
6
+ Publisher SDK for the [SovAds](https://ads.sovseas.xyz) ad network. Ships
7
+ seven modular surfaces (Banner, Sidebar, Popup, BottomBar, Overlay,
8
+ Interstitial, NativeCard) plus an opt-in **attached CTA** system that lets a
9
+ single ad carry up to two on-page tasks (visit-url, sign-message, poll) and
10
+ reward viewers for completing them.
11
+
12
+ - Zero peer dependencies. Works in any HTML page or framework (React, Vue,
13
+ Svelte, plain `<script type="module">`).
14
+ - Full TypeScript types.
15
+ - Backward compatible — every existing positional call site keeps working;
16
+ attached CTAs are strictly opt-in.
17
+
18
+ ---
4
19
 
5
20
  ## Installation
6
21
 
7
22
  ```bash
8
- npm install sovads-sdk
23
+ npm install sovads-sdk@latest
9
24
  # or
10
- pnpm add sovads-sdk
25
+ pnpm add sovads-sdk@latest
11
26
  # or
12
- yarn add sovads-sdk
27
+ yarn add sovads-sdk@latest
13
28
  ```
14
29
 
15
- ## Usage
30
+ CDN / no-bundler usage:
31
+
32
+ ```html
33
+ <script type="module">
34
+ import { SovAds, Banner } from 'https://ads.sovseas.xyz/api/v1/sdk'
35
+ const sovads = new SovAds({ debug: true })
36
+ await new Banner(sovads, 'banner').render()
37
+ </script>
38
+ ```
16
39
 
17
- ### Basic Setup
40
+ ---
18
41
 
19
- ```javascript
20
- import { SovAds, Banner, Popup, Sidebar } from 'sovads-sdk'
42
+ ## Quick start
43
+
44
+ ```ts
45
+ import { SovAds, Banner, Popup, Sidebar, BottomBar } from 'sovads-sdk'
21
46
 
22
- // Initialize SDK
23
47
  const sovads = new SovAds({
24
- apiUrl: 'https://ads.sovseas.xyz', // Optional, defaults to production URL
25
- debug: false, // Enable debug logging
26
- siteId: 'your-site-id', // Optional, will auto-detect if not provided
48
+ // apiUrl defaults to https://ads.sovseas.xyz in production builds; override
49
+ // for self-hosting or local dev.
50
+ apiUrl: 'https://ads.sovseas.xyz',
51
+ debug: false,
52
+ // Optional — auto-detected from the page origin if omitted.
53
+ siteId: 'your-site-id',
54
+ // Optional — viewer wallet for reward attribution.
55
+ walletAddress: '0x...',
27
56
  })
28
57
 
29
- // Banner Ad
30
- const banner = new Banner(sovads, 'banner-container')
31
- await banner.render()
58
+ // 1. Inline banner
59
+ await new Banner(sovads, 'banner-container').render()
32
60
 
33
- // Popup Ad
34
- const popup = new Popup(sovads)
35
- await popup.show() // Shows after 3 seconds by default
61
+ // 2. Sidebar
62
+ await new Sidebar(sovads, 'sidebar-container').render()
36
63
 
37
- // Bottom bar (floating banner at bottom with close button)
38
- const bottomBar = new BottomBar(sovads)
39
- await bottomBar.show()
64
+ // 3. Popup (modal, with frequency cap)
65
+ await new Popup(sovads).show()
40
66
 
41
- // Sidebar Ad
42
- const sidebar = new Sidebar(sovads, 'sidebar-container')
43
- await sidebar.render()
67
+ // 4. Bottom bar (sticky, dismissible)
68
+ await new BottomBar(sovads).show()
44
69
  ```
45
70
 
46
- ### HTML Example
71
+ ---
47
72
 
48
- ```html
49
- <!DOCTYPE html>
50
- <html>
51
- <head>
52
- <title>My Site with SovAds</title>
53
- </head>
54
- <body>
55
- <h1>Welcome to My Site</h1>
56
-
57
- <!-- Banner Ad Container -->
58
- <div id="banner-container"></div>
59
-
60
- <!-- Sidebar Ad Container -->
61
- <div id="sidebar-container"></div>
62
-
63
- <script type="module">
64
- import { SovAds, Banner, Sidebar } from 'sovads-sdk'
65
-
66
- const sovads = new SovAds({ debug: true })
67
- const banner = new Banner(sovads, 'banner-container')
68
- const sidebar = new Sidebar(sovads, 'sidebar-container')
69
-
70
- banner.render()
71
- sidebar.render()
72
- </script>
73
- </body>
74
- </html>
73
+ ## Attached CTAs (v1.1+)
74
+
75
+ A campaign can attach up to **2 tasks** to its banner. The SDK renders them
76
+ inline beneath the media. Reward issuance and HMAC-signed verification are
77
+ handled server-side; the SDK only mounts UI and reports submissions.
78
+
79
+ ```ts
80
+ import { Banner } from 'sovads-sdk'
81
+
82
+ const banner = new Banner(sovads, 'banner-container', {
83
+ attached: true, // ask the server for attached tasks
84
+ clickTarget: 'button', // optional: route click-through through an
85
+ // explicit "Learn more" button (recommended)
86
+ onCtaComplete: (ev) => {
87
+ if (ev.ok) {
88
+ console.log('rewarded', ev.awarded) // { points, gs, bonusPointsInLieuOfGs? }
89
+ } else if (ev.needsSignature) {
90
+ // SIGN_MESSAGE task — your wallet code should sign ev.needsSignature.message
91
+ }
92
+ },
93
+ })
94
+ await banner.render()
75
95
  ```
76
96
 
77
- ## API Reference
97
+ Supported task kinds:
78
98
 
79
- ### SovAds
99
+ | Kind | What the viewer does |
100
+ | --------------- | ------------------------------------------ |
101
+ | `VISIT_URL` | Clicks through and dwells `minDwellMs`. |
102
+ | `SIGN_MESSAGE` | Signs a short message with their wallet. |
103
+ | `POLL` | Picks one of up to 4 options. |
80
104
 
81
- Main SDK class for initialization and configuration.
105
+ If the campaign has no attached tasks, or you don't pass `attached: true`, the
106
+ SDK falls back to the classic banner-only experience.
82
107
 
83
- #### Constructor
108
+ ### Pure-CTA unit (no media)
84
109
 
85
- ```typescript
86
- new SovAds(config?: SovAdsConfig)
110
+ For a CTA-only slot (e.g. an inline poll under an article):
111
+
112
+ ```ts
113
+ import { CtaUnit } from 'sovads-sdk'
114
+
115
+ await new CtaUnit(sovads, 'poll-here').render({
116
+ layout: 'auto', // 'stack' | 'inline' | 'auto' (inline at 2 tasks)
117
+ onCtaComplete: (ev) => { /* … */ },
118
+ })
87
119
  ```
88
120
 
89
- #### Config Options
121
+ ---
122
+
123
+ ## API reference
124
+
125
+ ### `new SovAds(config?: SovAdsConfig)`
126
+
127
+ | Field | Type | Default | Notes |
128
+ | --------------------------- | -------------------------- | ----------------------------- | ------------------------------------------------------------------------------------ |
129
+ | `apiUrl` | `string` | `https://ads.sovseas.xyz` | API origin. Set to your local server in dev. |
130
+ | `siteId` | `string` | auto-detected | Publisher site ID. |
131
+ | `apiKey` / `apiSecret` | `string` | — | Enables HMAC-signed tracking. |
132
+ | `debug` | `boolean` | `false` | Verbose console logging. |
133
+ | `consumerId` | `string` | — | Target a specific advertiser slug. |
134
+ | `walletAddress` | `string` | — | Viewer wallet for reward attribution. |
135
+ | `refreshInterval` | `number` (seconds) | `0` (off) | Auto-refresh interval for Banner / Sidebar. |
136
+ | `lazyLoad` | `boolean` | `true` | Use IntersectionObserver to defer load until in-viewport. |
137
+ | `rotationEnabled` | `boolean` | `true` | Rotate between ads when refreshing. |
138
+ | `popupMinIntervalMinutes` | `number` | `30` | Min minutes between popup / overlay impressions per viewer. |
139
+ | `popupSessionMax` | `number` | `1` | Hard cap on popup / overlay impressions per browser session. |
140
+ | `disclosureLabel` | `boolean \| string` | `true` (`"Sponsored"`) | Force a custom label (e.g. `"Ad"`) or `false` to suppress (not recommended). |
141
+ | `advertiserName` | `string` | — | Appended to the disclosure: `"Sponsored · {advertiserName}"`. |
142
+
143
+ ### `Banner`
144
+
145
+ ```ts
146
+ new Banner(sovads, containerId, slotConfig?: SlotConfig)
147
+ banner.render(consumerId?: string, forceRefresh?: boolean): Promise<void>
148
+ ```
149
+
150
+ `SlotConfig`: `{ placementId?, size?, attached?, onCtaComplete?, clickTarget?, disclosureLabel? }`.
90
151
 
91
- - `apiUrl?: string` - API endpoint URL (default: `https://ads.sovseas.xyz`)
92
- - `debug?: boolean` - Enable debug logging (default: `false`)
93
- - `siteId?: string` - Site ID (optional, will auto-detect)
94
- - `consumerId?: string` - Consumer ID for targeting specific advertisers
152
+ ### `Sidebar`
95
153
 
96
- ### Banner
154
+ ```ts
155
+ new Sidebar(sovads, containerId, slotConfig?: SlotConfig)
156
+ sidebar.render(consumerId?: string, forceRefresh?: boolean): Promise<void>
157
+ ```
97
158
 
98
- Banner ad component.
159
+ ### `Popup`
99
160
 
100
- ```typescript
101
- const banner = new Banner(sovads: SovAds, containerId: string)
102
- await banner.render(consumerId?: string)
161
+ ```ts
162
+ new Popup(sovads)
163
+ popup.show(consumerIdOrOpts?: string | PopupShowOptions): Promise<void>
164
+ popup.hide(): void
103
165
  ```
104
166
 
105
- ### Popup
167
+ `PopupShowOptions`: `{ consumerId?, delay? (ms, default 3000), attached?, onCtaComplete?, clickTarget?, disclosureLabel? }`.
106
168
 
107
- Popup ad component.
169
+ ### `BottomBar`
108
170
 
109
- ```typescript
110
- const popup = new Popup(sovads: SovAds)
111
- await popup.show(consumerId?: string, delay?: number)
112
- popup.hide()
171
+ ```ts
172
+ new BottomBar(sovads)
173
+ bottomBar.show(consumerIdOrOpts?: string | BottomBarShowOptions): Promise<void>
174
+ bottomBar.hide(): void
113
175
  ```
114
176
 
115
- ### BottomBar
177
+ Defaults to `clickTarget: 'button'` to suppress accidental bar-wide clicks.
178
+
179
+ ### `Overlay` / `Interstitial`
180
+
181
+ `Overlay` is a full-viewport modal with backdrop dismiss. `Interstitial`
182
+ extends it with its own frequency-cap counter so the two surfaces never
183
+ share a budget.
116
184
 
117
- Floating bottom bar ad with a built-in close (`×`) button. Designed to sit fixed at the bottom of the viewport; click the `×` or the ad itself to dismiss. You can style the bar by targeting the `.sovads-bottom-bar` class in your CSS.
185
+ ```ts
186
+ new Overlay(sovads)
187
+ overlay.show(opts?: OverlayShowOptions): Promise<void>
188
+ overlay.hide(): void
118
189
 
119
- ```typescript
120
- const bottomBar = new BottomBar(sovads: SovAds)
121
- await bottomBar.show(consumerId?: string)
122
- bottomBar.hide()
190
+ new Interstitial(sovads) // same API
123
191
  ```
124
192
 
125
- ### Sidebar
193
+ `OverlayShowOptions`: `{ consumerId?, attached?, onCtaComplete?, clickTarget?, disclosureLabel?, dismissOnBackdrop? (default true), dismissOnEscape? (default true) }`.
126
194
 
127
- Sidebar ad component.
195
+ ### `NativeCard`
128
196
 
129
- ```typescript
130
- const sidebar = new Sidebar(sovads: SovAds, containerId: string)
131
- await sidebar.render(consumerId?: string)
197
+ ```ts
198
+ new NativeCard(sovads, containerId)
199
+ card.render(consumerIdOrOpts?: string | NativeCardRenderOptions): Promise<void>
132
200
  ```
133
201
 
202
+ ### `CtaUnit`
203
+
204
+ Pure CTA panel (no media). See [Attached CTAs](#attached-ctas-v11) above.
205
+
206
+ ### Other exports
207
+
208
+ - `SDK_VERSION` — runtime version string, kept in sync with `package.json`.
209
+ - `mountMedia`, `mountCtaPanel`, `renderAttachedCtas` — low-level building blocks for custom layouts.
210
+ - `buildRewardBadge`, `buildDisclosureBadge` — drop-in UI primitives.
211
+ - `toStreamingEmbed`, `buildStreamingIframe` — helpers for video creatives.
212
+ - Types: `SovAdsConfig`, `AdComponent`, `AttachedTask`, `AttachedTaskKind`, `AttachedPollOption`, `AttachedCtaCompleteEvent`, `SlotConfig`, `PopupShowOptions`, `BottomBarShowOptions`, `OverlayShowOptions`, `NativeCardRenderOptions`, `CtaUnitRenderOptions`, `AdSurface`.
213
+
214
+ ---
215
+
216
+ ## Styling
217
+
218
+ Every surface ships unstyled-friendly hooks; target these classes in your own
219
+ CSS to brand the units:
220
+
221
+ | Class | Surface |
222
+ | ------------------------------ | ------------- |
223
+ | `.sovads-banner` | Banner |
224
+ | `.sovads-sidebar` | Sidebar |
225
+ | `.sovads-popup-overlay` | Popup |
226
+ | `.sovads-bottom-bar` | BottomBar |
227
+ | `.sovads-overlay` | Overlay / Interstitial |
228
+ | `.sovads-native-card` | NativeCard |
229
+ | `.sovads-cta-panel` | Attached CTA panel (all surfaces) |
230
+ | `.sovads-disclosure` | "Sponsored" badge |
231
+ | `.sovads-reward-badge` | "Earn N pts" badge |
232
+
233
+ ---
234
+
235
+ ## Frequency capping
236
+
237
+ Popup, Overlay, and Interstitial each persist a `last-shown` timestamp in
238
+ `localStorage` and a session counter in `sessionStorage`. The same
239
+ `popupMinIntervalMinutes` / `popupSessionMax` knobs apply to all three —
240
+ publishers don't have to think about three sets of dials. Banner / Sidebar /
241
+ BottomBar / NativeCard do **not** frequency-cap (they're publisher-placed).
242
+
243
+ ---
244
+
245
+ ## Tracking
246
+
247
+ The SDK sends two events:
248
+
249
+ - `IMPRESSION` — fired once the creative is verified visible
250
+ (IntersectionObserver, ≥ 50% area for ≥ 1s by default).
251
+ - `CLICK` — fired on banner / button click-through.
252
+
253
+ Attached-CTA submissions go through the regular `/api/tasks/*` endpoints and
254
+ emit `onCtaComplete` callbacks.
255
+
256
+ All outbound tracking carries the `X-SovAds-SDK-Version` header so the server
257
+ can correlate metrics with SDK releases.
258
+
259
+ ---
260
+
134
261
  ## Features
135
262
 
136
- - Automatic site detection
137
- - Impression and click tracking
138
- - Render verification with IntersectionObserver
139
- - Image load error handling
140
- - Network retry logic
141
- - CORS support
142
- - TypeScript support
143
- - Debug logging
144
- - 🎨 Customizable styling via CSS classes (e.g. `.sovads-banner`, `.sovads-sidebar`, `.sovads-popup-overlay`, `.sovads-bottom-bar`)
263
+ - Automatic site detection
264
+ - IntersectionObserver-based viewability tracking
265
+ - Network retry with exponential backoff
266
+ - Image / video load error handling
267
+ - `navigator.sendBeacon` fallback for tracking on page unload
268
+ - Reduced-motion respect (`prefers-reduced-motion`)
269
+ - TypeScript-first
270
+ - Zero runtime dependencies
271
+
272
+ ## Browser support
273
+
274
+ Evergreen Chromium, Firefox, Safari (last 2 versions). Requires native
275
+ `IntersectionObserver` and ES2020.
145
276
 
146
277
  ## License
147
278
 
148
- MIT
279
+ MIT — see [LICENSE](https://github.com/sovseas/sovads/blob/main/sdk/LICENSE).
280
+
281
+ ## Links
149
282
 
283
+ - [Documentation](https://ads.sovseas.xyz/docs)
284
+ - [Repository](https://github.com/sovseas/sovads)
285
+ - [Issues](https://github.com/sovseas/sovads/issues)