@action-x/ad-sdk 0.1.11 → 0.1.13
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 +433 -150
- package/dist/index.cjs +31 -31
- package/dist/index.d.ts +7 -140
- package/dist/index.js +270 -492
- package/dist/index.umd.js +34 -34
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,185 +1,385 @@
|
|
|
1
|
-
# @action-x/ad-sdk
|
|
1
|
+
# @action-x/ad-sdk Usage Guide
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Zero-dependency ad SDK for AI conversations, supporting Vanilla JS, Vue, React, Next.js, and all frameworks.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
### Installation
|
|
8
10
|
|
|
9
11
|
```bash
|
|
10
12
|
npm install @action-x/ad-sdk
|
|
11
|
-
# or
|
|
12
|
-
yarn add @action-x/ad-sdk
|
|
13
|
-
# or
|
|
14
|
-
pnpm add @action-x/ad-sdk
|
|
15
13
|
```
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
### Minimal Example
|
|
18
16
|
|
|
19
|
-
```
|
|
17
|
+
```typescript
|
|
18
|
+
import { AdManager } from '@action-x/ad-sdk';
|
|
20
19
|
import '@action-x/ad-sdk/style.css';
|
|
20
|
+
|
|
21
|
+
const manager = new AdManager({
|
|
22
|
+
apiBaseUrl: 'https://network.actionx.top/api/v1',
|
|
23
|
+
apiKey: 'ak_your_api_key',
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Request ads after AI conversation completes
|
|
27
|
+
await manager.requestAds({
|
|
28
|
+
query: 'Recommend a Bluetooth headset',
|
|
29
|
+
response: 'AI response content...',
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Render ad
|
|
33
|
+
manager.render(document.getElementById('ad-container'));
|
|
21
34
|
```
|
|
22
35
|
|
|
23
36
|
---
|
|
24
37
|
|
|
25
|
-
##
|
|
38
|
+
## Core Concepts
|
|
26
39
|
|
|
27
|
-
|
|
40
|
+
### 1. AdManager Configuration
|
|
28
41
|
|
|
29
|
-
|
|
42
|
+
```typescript
|
|
43
|
+
const manager = new AdManager({
|
|
44
|
+
apiBaseUrl: string; // Required: API endpoint
|
|
45
|
+
apiKey: string; // Required: API key
|
|
46
|
+
cardOption?: { // Optional: Card configuration
|
|
47
|
+
variant?: 'horizontal' | 'vertical' | 'compact'; // Layout style
|
|
48
|
+
count?: number; // Number of ads to request, default 1
|
|
49
|
+
};
|
|
50
|
+
enabled?: boolean; // Enable ads, default true
|
|
51
|
+
debug?: boolean; // Debug mode, default false
|
|
52
|
+
});
|
|
53
|
+
```
|
|
30
54
|
|
|
31
|
-
|
|
32
|
-
<!-- AdCard.vue -->
|
|
33
|
-
<template>
|
|
34
|
-
<div ref="adEl" />
|
|
35
|
-
</template>
|
|
55
|
+
### 2. Request Ads
|
|
36
56
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
57
|
+
```typescript
|
|
58
|
+
// Simplified call (recommended)
|
|
59
|
+
await manager.requestAds({
|
|
60
|
+
query: string; // Required: User query
|
|
61
|
+
response: string; // Required: AI response content
|
|
62
|
+
});
|
|
41
63
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
64
|
+
// Full call
|
|
65
|
+
await manager.requestAds({
|
|
66
|
+
conversationContext: {
|
|
67
|
+
query: string;
|
|
68
|
+
response: string;
|
|
69
|
+
},
|
|
70
|
+
userContext?: {
|
|
71
|
+
sessionId?: string;
|
|
72
|
+
userId?: string;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
```
|
|
45
76
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
77
|
+
### 3. Render Ads
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
// Simplified call (renders action_card slot by default)
|
|
81
|
+
manager.render(
|
|
82
|
+
container: HTMLElement,
|
|
83
|
+
options?: {
|
|
84
|
+
adIndex?: number; // Ad index, default 0
|
|
85
|
+
variant?: string; // Layout variant
|
|
86
|
+
onClick?: (ad) => void; // Click callback
|
|
87
|
+
onImpression?: (ad) => void; // Impression callback
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// Specify slot
|
|
92
|
+
manager.render(
|
|
93
|
+
slotId: string,
|
|
94
|
+
container: HTMLElement,
|
|
95
|
+
options?: { ... }
|
|
96
|
+
);
|
|
97
|
+
```
|
|
51
98
|
|
|
52
|
-
|
|
99
|
+
### 4. Event Listeners
|
|
53
100
|
|
|
54
|
-
|
|
101
|
+
```typescript
|
|
102
|
+
manager.on('adsUpdated', (slots) => {
|
|
103
|
+
console.log('Ad data updated');
|
|
55
104
|
});
|
|
56
105
|
|
|
57
|
-
|
|
58
|
-
|
|
106
|
+
manager.on('adsLoading', () => {
|
|
107
|
+
console.log('Requesting ads');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
manager.on('adsError', (error) => {
|
|
111
|
+
console.warn('Ad request failed', error);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
manager.on('adClicked', (adId, slotId) => {
|
|
115
|
+
console.log('Ad clicked', adId);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
manager.on('adImpression', (adId, slotId) => {
|
|
119
|
+
console.log('Ad impression', adId);
|
|
120
|
+
});
|
|
59
121
|
```
|
|
60
122
|
|
|
61
|
-
|
|
123
|
+
---
|
|
62
124
|
|
|
63
|
-
|
|
64
|
-
// components/AdCard.tsx
|
|
65
|
-
import { useEffect, useRef } from 'react';
|
|
66
|
-
import { AdManager } from '@action-x/ad-sdk';
|
|
67
|
-
import '@action-x/ad-sdk/style.css';
|
|
125
|
+
## Framework Integration Examples
|
|
68
126
|
|
|
69
|
-
|
|
70
|
-
query: string;
|
|
71
|
-
response: string;
|
|
72
|
-
}
|
|
127
|
+
### Vanilla JavaScript
|
|
73
128
|
|
|
74
|
-
|
|
75
|
-
|
|
129
|
+
```html
|
|
130
|
+
<!DOCTYPE html>
|
|
131
|
+
<html>
|
|
132
|
+
<head>
|
|
133
|
+
<link rel="stylesheet" href="https://unpkg.com/@action-x/ad-sdk@latest/dist/style.css" />
|
|
134
|
+
</head>
|
|
135
|
+
<body>
|
|
136
|
+
<div id="ad-container"></div>
|
|
137
|
+
|
|
138
|
+
<script src="https://unpkg.com/@action-x/ad-sdk@latest/dist/index.umd.js"></script>
|
|
139
|
+
<script>
|
|
140
|
+
const { AdManager } = ActionXAdSDK;
|
|
76
141
|
|
|
77
|
-
useEffect(() => {
|
|
78
142
|
const manager = new AdManager({
|
|
79
|
-
apiBaseUrl: 'https://
|
|
143
|
+
apiBaseUrl: 'https://network.actionx.top/api/v1',
|
|
80
144
|
apiKey: 'ak_your_api_key',
|
|
145
|
+
debug: false,
|
|
81
146
|
});
|
|
82
147
|
|
|
83
|
-
manager
|
|
84
|
-
.
|
|
85
|
-
|
|
86
|
-
if (containerRef.current) {
|
|
87
|
-
manager.render(containerRef.current);
|
|
88
|
-
}
|
|
89
|
-
});
|
|
148
|
+
manager.on('adsUpdated', () => {
|
|
149
|
+
manager.render(document.getElementById('ad-container'));
|
|
150
|
+
});
|
|
90
151
|
|
|
91
|
-
|
|
92
|
-
|
|
152
|
+
// Call after conversation completes
|
|
153
|
+
function onChatComplete(query, response) {
|
|
154
|
+
manager.requestAds({ query, response });
|
|
155
|
+
}
|
|
156
|
+
</script>
|
|
157
|
+
</body>
|
|
158
|
+
</html>
|
|
159
|
+
```
|
|
93
160
|
|
|
94
|
-
|
|
95
|
-
|
|
161
|
+
### Vue 3
|
|
162
|
+
|
|
163
|
+
**Install and import styles:**
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
// main.ts
|
|
167
|
+
import { createApp } from 'vue';
|
|
168
|
+
import App from './App.vue';
|
|
169
|
+
import '@action-x/ad-sdk/style.css';
|
|
170
|
+
|
|
171
|
+
createApp(App).mount('#app');
|
|
96
172
|
```
|
|
97
173
|
|
|
98
|
-
|
|
174
|
+
**Create Composable:**
|
|
99
175
|
|
|
100
|
-
```
|
|
176
|
+
```typescript
|
|
177
|
+
// composables/useAdManager.ts
|
|
178
|
+
import { ref, shallowRef, onUnmounted } from 'vue';
|
|
101
179
|
import { AdManager } from '@action-x/ad-sdk';
|
|
102
|
-
import '@action-x/ad-sdk/style.css';
|
|
103
180
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
181
|
+
export function useAdManager() {
|
|
182
|
+
const manager = shallowRef(
|
|
183
|
+
new AdManager({
|
|
184
|
+
apiBaseUrl: 'https://network.actionx.top/api/v1',
|
|
185
|
+
apiKey: 'ak_your_api_key',
|
|
186
|
+
debug: false,
|
|
187
|
+
})
|
|
188
|
+
);
|
|
108
189
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
190
|
+
const isLoading = ref(false);
|
|
191
|
+
const error = ref<Error | null>(null);
|
|
192
|
+
|
|
193
|
+
manager.value.on('adsLoading', () => {
|
|
194
|
+
isLoading.value = true;
|
|
195
|
+
error.value = null;
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
manager.value.on('adsUpdated', () => {
|
|
199
|
+
isLoading.value = false;
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
manager.value.on('adsError', (e) => {
|
|
203
|
+
isLoading.value = false;
|
|
204
|
+
error.value = e;
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
onUnmounted(() => manager.value.destroy());
|
|
114
208
|
|
|
115
|
-
|
|
209
|
+
async function requestAds(query: string, response: string) {
|
|
210
|
+
await manager.value.requestAds({ query, response });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return { manager, isLoading, error, requestAds };
|
|
214
|
+
}
|
|
116
215
|
```
|
|
117
216
|
|
|
118
|
-
|
|
217
|
+
**Use in component:**
|
|
119
218
|
|
|
120
|
-
```
|
|
121
|
-
<
|
|
122
|
-
<
|
|
219
|
+
```vue
|
|
220
|
+
<template>
|
|
221
|
+
<div class="chat-response">
|
|
222
|
+
<div class="response-text">{{ responseText }}</div>
|
|
223
|
+
<div ref="adRef" class="ad-mount"></div>
|
|
224
|
+
</div>
|
|
225
|
+
</template>
|
|
123
226
|
|
|
124
|
-
<
|
|
227
|
+
<script setup lang="ts">
|
|
228
|
+
import { ref, watch, nextTick } from 'vue';
|
|
229
|
+
import { useAdManager } from '@/composables/useAdManager';
|
|
125
230
|
|
|
126
|
-
<
|
|
127
|
-
|
|
231
|
+
const props = defineProps<{
|
|
232
|
+
query: string;
|
|
233
|
+
responseText: string;
|
|
234
|
+
isStreaming: boolean;
|
|
235
|
+
}>();
|
|
236
|
+
|
|
237
|
+
const adRef = ref<HTMLElement>();
|
|
238
|
+
const { manager, requestAds } = useAdManager();
|
|
239
|
+
|
|
240
|
+
watch(
|
|
241
|
+
() => props.isStreaming,
|
|
242
|
+
async (streaming) => {
|
|
243
|
+
if (!streaming && props.responseText) {
|
|
244
|
+
await requestAds(props.query, props.responseText);
|
|
245
|
+
await nextTick();
|
|
246
|
+
|
|
247
|
+
if (adRef.value) {
|
|
248
|
+
manager.value.render(adRef.value);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
);
|
|
253
|
+
</script>
|
|
254
|
+
```
|
|
128
255
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
256
|
+
### React / Next.js
|
|
257
|
+
|
|
258
|
+
**Import styles:**
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
// Next.js App Router: app/layout.tsx
|
|
262
|
+
import '@action-x/ad-sdk/style.css';
|
|
263
|
+
|
|
264
|
+
export default function RootLayout({ children }) {
|
|
265
|
+
return <html><body>{children}</body></html>;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Vite + React: src/main.tsx
|
|
269
|
+
import '@action-x/ad-sdk/style.css';
|
|
270
|
+
import React from 'react';
|
|
271
|
+
import ReactDOM from 'react-dom/client';
|
|
272
|
+
import App from './App';
|
|
273
|
+
|
|
274
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(<App />);
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Create Hook:**
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
// hooks/useAdManager.ts
|
|
281
|
+
import { useEffect, useRef, useState, useCallback } from 'react';
|
|
282
|
+
import { AdManager } from '@action-x/ad-sdk';
|
|
283
|
+
|
|
284
|
+
export function useAdManager() {
|
|
285
|
+
const managerRef = useRef<AdManager | null>(null);
|
|
286
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
287
|
+
const [error, setError] = useState<Error | null>(null);
|
|
288
|
+
const [isReady, setIsReady] = useState(false);
|
|
133
289
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
290
|
+
useEffect(() => {
|
|
291
|
+
const manager = new AdManager({
|
|
292
|
+
apiBaseUrl: 'https://network.actionx.top/api/v1',
|
|
293
|
+
apiKey: 'ak_your_api_key',
|
|
294
|
+
debug: false,
|
|
138
295
|
});
|
|
139
|
-
|
|
296
|
+
|
|
297
|
+
manager.on('adsLoading', () => setIsLoading(true));
|
|
298
|
+
manager.on('adsUpdated', () => {
|
|
299
|
+
setIsLoading(false);
|
|
300
|
+
setIsReady(true);
|
|
301
|
+
});
|
|
302
|
+
manager.on('adsError', (e) => {
|
|
303
|
+
setIsLoading(false);
|
|
304
|
+
setError(e);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
managerRef.current = manager;
|
|
308
|
+
return () => manager.destroy();
|
|
309
|
+
}, []);
|
|
310
|
+
|
|
311
|
+
const requestAds = useCallback(async (query: string, response: string) => {
|
|
312
|
+
if (!managerRef.current) return;
|
|
313
|
+
await managerRef.current.requestAds({ query, response });
|
|
314
|
+
}, []);
|
|
315
|
+
|
|
316
|
+
return { manager: managerRef.current, isLoading, isReady, error, requestAds };
|
|
317
|
+
}
|
|
140
318
|
```
|
|
141
319
|
|
|
142
|
-
|
|
320
|
+
**Create Ad Component:**
|
|
143
321
|
|
|
144
|
-
|
|
322
|
+
```tsx
|
|
323
|
+
// components/AdCard.tsx
|
|
324
|
+
'use client';
|
|
145
325
|
|
|
146
|
-
|
|
326
|
+
import { useEffect, useRef } from 'react';
|
|
327
|
+
import type { AdManager } from '@action-x/ad-sdk';
|
|
147
328
|
|
|
148
|
-
|
|
329
|
+
interface AdCardProps {
|
|
330
|
+
manager: AdManager | null;
|
|
331
|
+
isReady: boolean;
|
|
332
|
+
className?: string;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function AdCard({ manager, isReady, className }: AdCardProps) {
|
|
336
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
337
|
+
|
|
338
|
+
useEffect(() => {
|
|
339
|
+
if (!isReady || !manager || !containerRef.current) return;
|
|
340
|
+
manager.render(containerRef.current);
|
|
341
|
+
}, [isReady, manager]);
|
|
342
|
+
|
|
343
|
+
return <div ref={containerRef} className={className} />;
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**Use in page:**
|
|
149
348
|
|
|
150
349
|
```tsx
|
|
350
|
+
// app/chat/page.tsx
|
|
351
|
+
'use client';
|
|
352
|
+
|
|
151
353
|
import { useState } from 'react';
|
|
152
|
-
import {
|
|
354
|
+
import { useAdManager } from '@/hooks/useAdManager';
|
|
355
|
+
import { AdCard } from '@/components/AdCard';
|
|
153
356
|
|
|
154
|
-
export function
|
|
357
|
+
export default function ChatPage() {
|
|
155
358
|
const [query, setQuery] = useState('');
|
|
156
359
|
const [response, setResponse] = useState('');
|
|
157
360
|
const [isStreaming, setIsStreaming] = useState(false);
|
|
158
361
|
|
|
159
|
-
|
|
160
|
-
setQuery(userQuery);
|
|
161
|
-
setIsStreaming(true);
|
|
162
|
-
setResponse('');
|
|
163
|
-
|
|
164
|
-
// Receive AI response as a stream
|
|
165
|
-
const stream = await fetchAIResponse(userQuery);
|
|
166
|
-
let fullResponse = '';
|
|
167
|
-
for await (const chunk of stream) {
|
|
168
|
-
fullResponse += chunk;
|
|
169
|
-
setResponse(fullResponse);
|
|
170
|
-
}
|
|
362
|
+
const { manager, isReady, requestAds } = useAdManager();
|
|
171
363
|
|
|
364
|
+
const handleSend = async () => {
|
|
365
|
+
setIsStreaming(true);
|
|
366
|
+
const aiResponse = await fetchAIResponse(query);
|
|
367
|
+
setResponse(aiResponse);
|
|
172
368
|
setIsStreaming(false);
|
|
173
|
-
|
|
174
|
-
|
|
369
|
+
|
|
370
|
+
await requestAds(query, aiResponse);
|
|
371
|
+
};
|
|
175
372
|
|
|
176
373
|
return (
|
|
177
374
|
<div>
|
|
178
|
-
<
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
{
|
|
182
|
-
<
|
|
375
|
+
<input value={query} onChange={(e) => setQuery(e.target.value)} />
|
|
376
|
+
<button onClick={handleSend}>Send</button>
|
|
377
|
+
|
|
378
|
+
{response && (
|
|
379
|
+
<div>
|
|
380
|
+
<p>{response}</p>
|
|
381
|
+
<AdCard manager={manager} isReady={isReady} className="mt-4" />
|
|
382
|
+
</div>
|
|
183
383
|
)}
|
|
184
384
|
</div>
|
|
185
385
|
);
|
|
@@ -188,63 +388,146 @@ export function ChatMessage() {
|
|
|
188
388
|
|
|
189
389
|
---
|
|
190
390
|
|
|
191
|
-
##
|
|
391
|
+
## Custom Styles
|
|
392
|
+
|
|
393
|
+
The SDK uses the `ax-ad-*` namespace. Override styles via CSS:
|
|
394
|
+
|
|
395
|
+
```css
|
|
396
|
+
/* Custom CTA button */
|
|
397
|
+
.ax-ad-cta {
|
|
398
|
+
background-color: #7c3aed !important;
|
|
399
|
+
border-radius: 20px;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.ax-ad-cta:hover {
|
|
403
|
+
background-color: #6d28d9 !important;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/* Custom card style */
|
|
407
|
+
.ax-ad-card {
|
|
408
|
+
border: none;
|
|
409
|
+
border-radius: 12px;
|
|
410
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
|
411
|
+
}
|
|
192
412
|
|
|
193
|
-
|
|
413
|
+
/* Dark mode */
|
|
414
|
+
@media (prefers-color-scheme: dark) {
|
|
415
|
+
.ax-ad-card {
|
|
416
|
+
background: #1f2937;
|
|
417
|
+
border-color: #374151;
|
|
418
|
+
color: #f9fafb;
|
|
419
|
+
}
|
|
420
|
+
.ax-ad-title { color: #f9fafb; }
|
|
421
|
+
.ax-ad-body { color: #9ca3af; }
|
|
422
|
+
}
|
|
194
423
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
424
|
+
/* Hide on mobile */
|
|
425
|
+
@media (max-width: 640px) {
|
|
426
|
+
.ax-ad-card { display: none; }
|
|
427
|
+
}
|
|
428
|
+
```
|
|
200
429
|
|
|
201
|
-
|
|
430
|
+
---
|
|
202
431
|
|
|
203
|
-
|
|
204
|
-
|------|------|--------|------|
|
|
205
|
-
| `variant` | `'horizontal' \| 'vertical' \| 'compact'` | `'horizontal'` | Layout style |
|
|
206
|
-
| `count` | `number` | `1` | Number of ads to request |
|
|
432
|
+
## Debugging Tips
|
|
207
433
|
|
|
208
|
-
|
|
434
|
+
### Enable Debug Logging
|
|
209
435
|
|
|
210
|
-
```
|
|
211
|
-
new AdManager({
|
|
436
|
+
```typescript
|
|
437
|
+
const manager = new AdManager({
|
|
212
438
|
apiBaseUrl: '...',
|
|
213
439
|
apiKey: '...',
|
|
214
|
-
|
|
215
|
-
variant: 'vertical',
|
|
216
|
-
count: 2,
|
|
217
|
-
},
|
|
440
|
+
debug: true, // Outputs detailed logs to console
|
|
218
441
|
});
|
|
219
442
|
```
|
|
220
443
|
|
|
221
|
-
###
|
|
444
|
+
### Check Ad Response
|
|
222
445
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
| `response` | `string` | Yes | AI response text |
|
|
446
|
+
```typescript
|
|
447
|
+
manager.on('adsUpdated', (slots) => {
|
|
448
|
+
console.log('Ad slots:', Object.keys(slots));
|
|
227
449
|
|
|
228
|
-
|
|
450
|
+
Object.entries(slots).forEach(([slotId, slot]) => {
|
|
451
|
+
console.log(`[${slotId}] Status:`, slot.status);
|
|
452
|
+
console.log(`[${slotId}] Ad count:`, slot.ads.length);
|
|
229
453
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
454
|
+
if (slot.status === 'no_fill') {
|
|
455
|
+
console.log(' → No fill (insufficient inventory or targeting mismatch)');
|
|
456
|
+
}
|
|
457
|
+
if (slot.status === 'error') {
|
|
458
|
+
console.error(' → Slot error:', slot.error);
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Common Issues
|
|
465
|
+
|
|
466
|
+
| Issue | Possible Cause | Solution |
|
|
467
|
+
|-------|---------------|----------|
|
|
468
|
+
| Empty ad container | `render()` called before `requestAds()` completes | Call `render()` inside `adsUpdated` event |
|
|
469
|
+
| Styles not applied | Forgot to import CSS | Ensure `import '@action-x/ad-sdk/style.css'` |
|
|
470
|
+
| Console 403 error | Invalid or missing apiKey | Check apiKey configuration |
|
|
471
|
+
| TypeScript type errors | Type definitions not generated | Run `npm run build` |
|
|
472
|
+
| Ad status 'no_fill' | No matching ads | Expected behavior, check `manager.hasAds()` before rendering |
|
|
473
|
+
| Clicks unresponsive | Container obscured | Check CSS z-index and pointer-events |
|
|
235
474
|
|
|
236
475
|
---
|
|
237
476
|
|
|
238
|
-
##
|
|
477
|
+
## API Reference
|
|
478
|
+
|
|
479
|
+
### AdManager
|
|
480
|
+
|
|
481
|
+
#### Constructor
|
|
239
482
|
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
manager.on('adsLoading', () => { /* requesting */ });
|
|
243
|
-
manager.on('adsError', (err) => { /* request failed */ });
|
|
244
|
-
manager.on('adClicked', (adId, slotId) => { });
|
|
245
|
-
manager.on('adImpression', (adId, slotId) => { });
|
|
483
|
+
```typescript
|
|
484
|
+
new AdManager(config: AdManagerConfig)
|
|
246
485
|
```
|
|
247
486
|
|
|
487
|
+
#### Methods
|
|
488
|
+
|
|
489
|
+
```typescript
|
|
490
|
+
// Request ads
|
|
491
|
+
requestAds(context: { query: string; response: string }): Promise<AdResponseBatch>
|
|
492
|
+
requestAds(context: { conversationContext, userContext? }): Promise<AdResponseBatch>
|
|
493
|
+
|
|
494
|
+
// Render ads
|
|
495
|
+
render(container: HTMLElement, options?: RenderOptions): HTMLElement | null
|
|
496
|
+
render(slotId: string, container: HTMLElement, options?: RenderOptions): HTMLElement | null
|
|
497
|
+
|
|
498
|
+
// Check if ads available
|
|
499
|
+
hasAds(slotId: string): boolean
|
|
500
|
+
|
|
501
|
+
// Get ad data
|
|
502
|
+
getAds(slotId: string): any[]
|
|
503
|
+
getSlots(slotId?: string): Record<string, AdSlotResponse> | AdSlotResponse | undefined
|
|
504
|
+
|
|
505
|
+
// Destroy instance
|
|
506
|
+
destroy(): void
|
|
507
|
+
|
|
508
|
+
// Event listeners
|
|
509
|
+
on(event: string, handler: Function): void
|
|
510
|
+
off(event: string, handler: Function): void
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
#### Events
|
|
514
|
+
|
|
515
|
+
- `adsLoading` - Started requesting ads
|
|
516
|
+
- `adsUpdated` - Ad data updated
|
|
517
|
+
- `adsError` - Request failed
|
|
518
|
+
- `adClicked` - Ad clicked
|
|
519
|
+
- `adImpression` - Ad impression
|
|
520
|
+
|
|
248
521
|
---
|
|
249
522
|
|
|
250
|
-
|
|
523
|
+
## Version Info
|
|
524
|
+
|
|
525
|
+
- Current version: `0.1.12`
|
|
526
|
+
- License: MIT
|
|
527
|
+
- Repository: [GitHub](https://github.com/action-x/ad-sdk)
|
|
528
|
+
|
|
529
|
+
---
|
|
530
|
+
|
|
531
|
+
## Support
|
|
532
|
+
|
|
533
|
+
For questions, contact ActionX support or submit an Issue.
|