@adstage/web-sdk 3.0.1 → 3.0.3
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.ko.md +508 -0
- package/README.md +163 -527
- package/dist/index.cjs.js +1 -4714
- package/dist/index.d.ts +42 -35
- package/dist/index.esm.js +1 -4703
- package/dist/index.standalone.js +2 -4767
- package/dist/index.umd.js +3 -4785
- package/package.json +5 -2
- package/src/events/global-events.ts +33 -15
- package/src/index.ts +2 -2
- package/src/managers/events/event-device-collector.ts +73 -9
- package/src/modules/events/events-module.ts +3 -46
- package/src/types/events.ts +25 -0
package/README.md
CHANGED
|
@@ -1,47 +1,20 @@
|
|
|
1
|
-
#
|
|
1
|
+
# adstage Web SDK
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> JavaScript/TypeScript SDK for AdStage marketing platform
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/@adstage/web-sdk)
|
|
6
6
|
[](http://www.typescriptlang.org/)
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## ✨
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- **이벤트 추적**: 노출, 클릭, 뷰어빌리티 등 자동 추적
|
|
19
|
-
- **중복 방지**: 동일 광고 중복 노출 방지 시스템
|
|
20
|
-
|
|
21
|
-
### 🏗️ 모듈화 아키텍처 (v2.5.3+)
|
|
22
|
-
- **팩토리 패턴**: AdRenderer가 광고 타입에 따라 적절한 렌더러 선택
|
|
23
|
-
- **타입별 렌더러**:
|
|
24
|
-
- `BannerAdRenderer`: 배너 광고 최적화 및 이미지 처리
|
|
25
|
-
- `TextAdRenderer`: 텍스트 전환 효과 및 스타일링
|
|
26
|
-
- `VideoAdRenderer`: 비디오 컨트롤 커스터마이징 및 폴백
|
|
27
|
-
- `NativeAdRenderer`: 네이티브 광고 레이아웃
|
|
28
|
-
- `InterstitialAdRenderer`: 전면 광고 오버레이
|
|
29
|
-
- **공통 인터페이스**: 일관된 API와 확장 가능한 구조
|
|
30
|
-
- **독립적 유지보수**: 각 광고 타입별 독립적 개발 및 테스트 가능
|
|
31
|
-
|
|
32
|
-
### ⚙️ 설정 관리 (완전 구현)
|
|
33
|
-
- **동기 초기화**: `await` 없이 즉시 사용 가능
|
|
34
|
-
- **모듈 선택**: 필요한 기능만 선택적 로드
|
|
35
|
-
- **환경 자동 감지**: 개발/프로덕션 환경 자동 설정
|
|
36
|
-
- **런타임 설정 변경**: 실시간 설정 업데이트
|
|
37
|
-
|
|
38
|
-
### 📊 이벤트 추적 (기본 구조 완성)
|
|
39
|
-
- **커스텀 이벤트**: 사용자 정의 이벤트 추적
|
|
40
|
-
- **페이지 뷰**: 자동 페이지 방문 추적
|
|
41
|
-
- **배치 처리**: 효율적인 이벤트 전송
|
|
42
|
-
- **오프라인 지원**: 네트워크 오류 시 로컬 저장
|
|
43
|
-
|
|
44
|
-
## 📦 설치
|
|
9
|
+
Lightweight SDK for rendering ads (banner / text / video) and tracking user events.
|
|
10
|
+
|
|
11
|
+
## ✨ Features
|
|
12
|
+
|
|
13
|
+
- Ad rendering: banner, text, video
|
|
14
|
+
- Event tracking: clicks, page views, custom events
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## 📦 Installation
|
|
45
18
|
|
|
46
19
|
```bash
|
|
47
20
|
# npm
|
|
@@ -54,573 +27,236 @@ yarn add @adstage/web-sdk
|
|
|
54
27
|
pnpm add @adstage/web-sdk
|
|
55
28
|
```
|
|
56
29
|
|
|
57
|
-
## 🚀
|
|
30
|
+
## 🚀 Quick Start
|
|
58
31
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
32
|
+
```javascript
|
|
62
33
|
import { AdStage } from '@adstage/web-sdk';
|
|
63
34
|
|
|
64
|
-
// 1. SDK 초기화 (동기)
|
|
65
35
|
AdStage.init({
|
|
66
|
-
apiKey: 'your-api-key'
|
|
67
|
-
debug: true,
|
|
68
|
-
modules: ['ads', 'config'] // 필요한 모듈만 로드
|
|
36
|
+
apiKey: 'your-api-key'
|
|
69
37
|
});
|
|
70
38
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
height: 250,
|
|
75
|
-
autoSlide: true,
|
|
76
|
-
slideInterval: 5000
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// 3. 텍스트 광고
|
|
80
|
-
const textId = AdStage.ads.text('text-container', {
|
|
81
|
-
maxLines: 3,
|
|
82
|
-
style: 'card'
|
|
83
|
-
});
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## 🏗️ 아키텍처 구조
|
|
87
|
-
|
|
88
|
-
### 광고 렌더링 시스템
|
|
89
|
-
|
|
90
|
-
```
|
|
91
|
-
AdRenderer (Factory)
|
|
92
|
-
├── IAdRenderer (Interface)
|
|
93
|
-
├── BaseAdRenderer (Base Class)
|
|
94
|
-
└── renderers/
|
|
95
|
-
├── BannerAdRenderer - 배너 광고 (이미지 최적화, 비율 계산)
|
|
96
|
-
├── TextAdRenderer - 텍스트 광고 (전환 효과, 스타일링)
|
|
97
|
-
├── VideoAdRenderer - 비디오 광고 (컨트롤 커스터마이징)
|
|
98
|
-
├── NativeAdRenderer - 네이티브 광고 (레이아웃 구성)
|
|
99
|
-
└── InterstitialAdRenderer - 전면 광고 (오버레이, 모달)
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### 주요 클래스 관계
|
|
103
|
-
|
|
104
|
-
```mermaid
|
|
105
|
-
graph TD
|
|
106
|
-
A[AdStage] --> B[AdsModule]
|
|
107
|
-
B --> C[AdRenderer Factory]
|
|
108
|
-
C --> D[IAdRenderer Interface]
|
|
109
|
-
D --> E[BaseAdRenderer]
|
|
110
|
-
E --> F[BannerAdRenderer]
|
|
111
|
-
E --> G[TextAdRenderer]
|
|
112
|
-
E --> H[VideoAdRenderer]
|
|
113
|
-
E --> I[NativeAdRenderer]
|
|
114
|
-
E --> J[InterstitialAdRenderer]
|
|
115
|
-
|
|
116
|
-
F --> K[CarouselSliderManager]
|
|
117
|
-
G --> L[TextTransitionManager]
|
|
118
|
-
|
|
119
|
-
C --> M[AdvertisementEventTracker]
|
|
120
|
-
C --> N[ViewableEventTracker]
|
|
39
|
+
AdStage.ads.banner('banner-container');
|
|
40
|
+
AdStage.ads.text('text-container');
|
|
41
|
+
AdStage.ads.video('video-container');
|
|
121
42
|
```
|
|
122
43
|
|
|
123
|
-
|
|
44
|
+
## 📖 Usage Examples
|
|
124
45
|
|
|
125
|
-
|
|
126
|
-
|--------|-----------|-----------|
|
|
127
|
-
| **BannerAdRenderer** | 이미지 최적화, 비율 계산 | 스마트 크기 조정, 다중 이미지 슬라이더 |
|
|
128
|
-
| **TextAdRenderer** | 텍스트 전환, 스타일링 | 페이드 효과, 라인 제한, 그라디언트 배경 |
|
|
129
|
-
| **VideoAdRenderer** | 비디오 제어, 폴백 처리 | 컨트롤 커스터마이징, 자동 이미지 폴백 |
|
|
130
|
-
| **NativeAdRenderer** | 네이티브 레이아웃 | 제목/설명/CTA 구조화, 자연스러운 디자인 |
|
|
131
|
-
| **InterstitialAdRenderer** | 전면 오버레이 | 모달 UI, ESC/클릭 닫기, 애니메이션 |
|
|
46
|
+
### 1. Ad Rendering
|
|
132
47
|
|
|
133
|
-
|
|
48
|
+
#### Plain HTML (UMD)
|
|
134
49
|
|
|
135
50
|
```html
|
|
136
51
|
<!DOCTYPE html>
|
|
137
52
|
<html>
|
|
138
|
-
<head>
|
|
139
|
-
<title>AdStage 예제</title>
|
|
140
|
-
</head>
|
|
141
53
|
<body>
|
|
142
|
-
|
|
143
|
-
<div id="
|
|
144
|
-
<div id="
|
|
145
|
-
|
|
146
|
-
<script
|
|
147
|
-
|
|
148
|
-
|
|
54
|
+
<div id="banner-ad"></div>
|
|
55
|
+
<div id="text-ad"></div>
|
|
56
|
+
<div id="video-ad"></div>
|
|
57
|
+
|
|
58
|
+
<script src="https://unpkg.com/@adstage/web-sdk/dist/index.umd.js"></script>
|
|
59
|
+
<script>
|
|
149
60
|
AdStage.init({ apiKey: 'your-api-key' });
|
|
150
|
-
AdStage.ads.banner('banner-
|
|
151
|
-
AdStage.ads.text('text-
|
|
61
|
+
AdStage.ads.banner('banner-ad');
|
|
62
|
+
AdStage.ads.text('text-ad');
|
|
63
|
+
AdStage.ads.video('video-ad');
|
|
152
64
|
</script>
|
|
153
65
|
</body>
|
|
154
66
|
</html>
|
|
155
67
|
```
|
|
156
68
|
|
|
157
|
-
|
|
69
|
+
#### ES Module (Standalone build)
|
|
158
70
|
|
|
159
|
-
|
|
71
|
+
```javascript
|
|
72
|
+
import { AdStage } from 'https://unpkg.com/@adstage/web-sdk/dist/index.standalone.js';
|
|
160
73
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
height: 250, // 높이 (px)
|
|
166
|
-
autoSlide: true, // 자동 슬라이드
|
|
167
|
-
slideInterval: 5000, // 슬라이드 간격 (ms)
|
|
168
|
-
onClick: (adData) => { // 클릭 콜백
|
|
169
|
-
console.log('Ad clicked:', adData);
|
|
170
|
-
}
|
|
171
|
-
});
|
|
74
|
+
AdStage.init({ apiKey: 'your-api-key' });
|
|
75
|
+
AdStage.ads.banner('banner-ad');
|
|
76
|
+
AdStage.ads.text('text-ad');
|
|
77
|
+
AdStage.ads.video('video-ad');
|
|
172
78
|
```
|
|
173
79
|
|
|
174
|
-
####
|
|
175
|
-
```typescript
|
|
176
|
-
const textId = AdStage.ads.text('container-id', {
|
|
177
|
-
maxLines: 3, // 최대 라인 수
|
|
178
|
-
style: 'card', // 스타일 ('default', 'card')
|
|
179
|
-
onClick: (adData) => { // 클릭 콜백
|
|
180
|
-
console.log('Text ad clicked:', adData);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
```
|
|
80
|
+
#### React (Basic)
|
|
184
81
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
width: 640,
|
|
189
|
-
height: 360,
|
|
190
|
-
autoplay: false, // 자동 재생
|
|
191
|
-
muted: true, // 음소거
|
|
192
|
-
onClick: (adData) => {
|
|
193
|
-
console.log('Video ad clicked:', adData);
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
#### 광고 관리
|
|
199
|
-
```typescript
|
|
200
|
-
// 광고 새로고침
|
|
201
|
-
AdStage.ads.refresh('slot-id');
|
|
202
|
-
|
|
203
|
-
// 광고 제거
|
|
204
|
-
AdStage.ads.destroy('slot-id');
|
|
205
|
-
|
|
206
|
-
// 모든 광고 슬롯 조회
|
|
207
|
-
const allSlots = AdStage.ads.getAllSlots();
|
|
82
|
+
```jsx
|
|
83
|
+
import { useEffect, useRef } from 'react';
|
|
84
|
+
import { AdStage } from '@adstage/web-sdk';
|
|
208
85
|
|
|
209
|
-
|
|
210
|
-
const
|
|
86
|
+
export function Banner() {
|
|
87
|
+
const ref = useRef(null);
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
AdStage.init({ apiKey: 'your-api-key' });
|
|
90
|
+
AdStage.ads.banner(ref.current.id);
|
|
91
|
+
}, []);
|
|
92
|
+
return <div id="banner-ad" ref={ref} />;
|
|
93
|
+
}
|
|
211
94
|
```
|
|
212
95
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
```typescript
|
|
216
|
-
// 현재 설정 조회
|
|
217
|
-
const config = AdStage.config.getConfig();
|
|
96
|
+
#### React (Provider + Hook)
|
|
218
97
|
|
|
219
|
-
|
|
220
|
-
|
|
98
|
+
```jsx
|
|
99
|
+
import { AdStageProvider, useAdStageInstance } from '@adstage/web-sdk';
|
|
100
|
+
import { useEffect, useRef } from 'react';
|
|
221
101
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
});
|
|
102
|
+
export function App() {
|
|
103
|
+
return (
|
|
104
|
+
<AdStageProvider config={{ apiKey: 'your-api-key' }}>
|
|
105
|
+
<Banner />
|
|
106
|
+
</AdStageProvider>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
230
109
|
|
|
231
|
-
|
|
232
|
-
const
|
|
110
|
+
function Banner() {
|
|
111
|
+
const ref = useRef(null);
|
|
112
|
+
const adstage = useAdStageInstance();
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
if (adstage && ref.current) adstage.ads.banner(ref.current.id);
|
|
115
|
+
}, [adstage]);
|
|
116
|
+
return <div id="banner-ad" ref={ref} />;
|
|
117
|
+
}
|
|
233
118
|
```
|
|
234
119
|
|
|
235
|
-
###
|
|
120
|
+
### 2. Event Tracking
|
|
121
|
+
|
|
122
|
+
#### Plain JS
|
|
236
123
|
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
await AdStage.events.track('button_click', {
|
|
124
|
+
```javascript
|
|
125
|
+
AdStage.events.track('button_click', {
|
|
240
126
|
button_id: 'cta',
|
|
241
|
-
page: '/
|
|
127
|
+
page: '/home'
|
|
242
128
|
});
|
|
243
129
|
|
|
244
|
-
|
|
245
|
-
await AdStage.events.pageView({
|
|
130
|
+
AdStage.events.track('page_view', {
|
|
246
131
|
page: '/products',
|
|
247
|
-
title: 'Products
|
|
248
|
-
category: 'shopping'
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
// 사용자 액션 추적
|
|
252
|
-
await AdStage.events.userAction('form_submit', {
|
|
253
|
-
form_id: 'contact',
|
|
254
|
-
email: 'user@example.com'
|
|
132
|
+
title: 'Products'
|
|
255
133
|
});
|
|
256
|
-
|
|
257
|
-
// 배치 이벤트 처리
|
|
258
|
-
AdStage.events.batch.start();
|
|
259
|
-
AdStage.events.batch.add('event1', { data: 'value1' });
|
|
260
|
-
AdStage.events.batch.add('event2', { data: 'value2' });
|
|
261
|
-
await AdStage.events.batch.flush();
|
|
262
134
|
```
|
|
263
135
|
|
|
264
|
-
|
|
136
|
+
#### Using Global Helpers
|
|
265
137
|
|
|
266
|
-
|
|
138
|
+
```javascript
|
|
139
|
+
import { track, setUserId, setUserProperties } from '@adstage/web-sdk';
|
|
267
140
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
apiKey: 'your-api-key',
|
|
272
|
-
modules: ['ads']
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
// 모든 기능 사용 (~28KB)
|
|
276
|
-
AdStage.init({
|
|
277
|
-
apiKey: 'your-api-key',
|
|
278
|
-
modules: ['ads', 'events', 'config']
|
|
279
|
-
});
|
|
141
|
+
track('purchase', { value: 99 });
|
|
142
|
+
setUserId('user123');
|
|
143
|
+
setUserProperties({ country: 'KR', gender: 'male' });
|
|
280
144
|
```
|
|
281
145
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
285
|
-
// 개발 환경
|
|
286
|
-
AdStage.init({
|
|
287
|
-
apiKey: 'dev-api-key',
|
|
288
|
-
baseUrl: 'https://beta-api.adstage.app', // 베타 환경
|
|
289
|
-
debug: true,
|
|
290
|
-
validateOnInit: false
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
// 프로덕션 환경
|
|
294
|
-
AdStage.init({
|
|
295
|
-
apiKey: 'prod-api-key',
|
|
296
|
-
baseUrl: 'https://api.adstage.io', // 프로덕션 환경
|
|
297
|
-
debug: false,
|
|
298
|
-
productionMode: true,
|
|
299
|
-
timeout: 10000
|
|
300
|
-
});
|
|
301
|
-
```
|
|
146
|
+
## ⚙️ Configuration
|
|
302
147
|
|
|
303
|
-
###
|
|
148
|
+
### Basic Initialization
|
|
304
149
|
|
|
305
|
-
```
|
|
150
|
+
```javascript
|
|
306
151
|
AdStage.init({
|
|
307
152
|
apiKey: 'your-api-key',
|
|
308
|
-
fallbackMode: true, // 네트워크 오류 시 fallback 모드
|
|
309
|
-
offlineMode: false, // 오프라인 모드 비활성화
|
|
310
153
|
debug: true
|
|
311
154
|
});
|
|
312
|
-
|
|
313
|
-
try {
|
|
314
|
-
const bannerId = AdStage.ads.banner('container');
|
|
315
|
-
} catch (error) {
|
|
316
|
-
console.error('광고 로드 실패:', error);
|
|
317
|
-
// fallback 처리
|
|
318
|
-
}
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
## 📱 React 통합
|
|
322
|
-
|
|
323
|
-
```tsx
|
|
324
|
-
import React, { useEffect, useRef } from 'react';
|
|
325
|
-
import { AdStage } from '@adstage/web-sdk';
|
|
326
|
-
|
|
327
|
-
// React 컴포넌트 예제
|
|
328
|
-
function AdBanner({ adType = 'banner', options = {} }) {
|
|
329
|
-
const containerRef = useRef<HTMLDivElement>(null);
|
|
330
|
-
const slotIdRef = useRef<string | null>(null);
|
|
331
|
-
|
|
332
|
-
useEffect(() => {
|
|
333
|
-
if (!containerRef.current) return;
|
|
334
|
-
|
|
335
|
-
// SDK 초기화 (한 번만)
|
|
336
|
-
if (!AdStage.config.isReady()) {
|
|
337
|
-
AdStage.init({
|
|
338
|
-
apiKey: process.env.REACT_APP_ADSTAGE_API_KEY!,
|
|
339
|
-
debug: process.env.NODE_ENV === 'development'
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// 광고 생성
|
|
344
|
-
const containerId = `ad-container-${Date.now()}`;
|
|
345
|
-
containerRef.current.id = containerId;
|
|
346
|
-
|
|
347
|
-
slotIdRef.current = AdStage.ads[adType](containerId, options);
|
|
348
|
-
|
|
349
|
-
// 정리
|
|
350
|
-
return () => {
|
|
351
|
-
if (slotIdRef.current) {
|
|
352
|
-
AdStage.ads.destroy(slotIdRef.current);
|
|
353
|
-
}
|
|
354
|
-
};
|
|
355
|
-
}, [adType, options]);
|
|
356
|
-
|
|
357
|
-
return <div ref={containerRef} />;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// 사용법
|
|
361
|
-
function App() {
|
|
362
|
-
return (
|
|
363
|
-
<div>
|
|
364
|
-
<AdBanner
|
|
365
|
-
adType="banner"
|
|
366
|
-
options={{ width: '100%', height: 250 }}
|
|
367
|
-
/>
|
|
368
|
-
<AdBanner
|
|
369
|
-
adType="text"
|
|
370
|
-
options={{ maxLines: 3, style: 'card' }}
|
|
371
|
-
/>
|
|
372
|
-
</div>
|
|
373
|
-
);
|
|
374
|
-
}
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
## 🏗 아키텍처 & 특징
|
|
378
|
-
|
|
379
|
-
### 네임스페이스 아키텍처
|
|
380
|
-
모든 기능이 `AdStage` 네임스페이스 하위에 체계적으로 구성되어 다른 라이브러리와의 충돌을 방지합니다.
|
|
381
|
-
|
|
382
|
-
```typescript
|
|
383
|
-
AdStage.ads.banner() // 광고 기능
|
|
384
|
-
AdStage.config.update() // 설정 관리
|
|
385
|
-
AdStage.events.track() // 이벤트 추적
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
### 모듈 시스템
|
|
389
|
-
필요한 기능만 선택적으로 로드하여 번들 크기를 최적화할 수 있습니다.
|
|
390
|
-
|
|
391
|
-
| 모듈 조합 | 크기 | 포함 기능 |
|
|
392
|
-
|-----------|------|-----------|
|
|
393
|
-
| `['ads']` | ~15KB | 광고 표시만 |
|
|
394
|
-
| `['ads', 'config']` | ~20KB | 광고 + 설정 관리 |
|
|
395
|
-
| `['ads', 'events', 'config']` | ~28KB | 모든 기능 |
|
|
396
|
-
|
|
397
|
-
### TypeScript 완전 지원
|
|
398
|
-
모든 API에 대한 완전한 타입 정의를 제공하여 개발 경험을 향상시킵니다.
|
|
399
|
-
|
|
400
|
-
```typescript
|
|
401
|
-
interface AdStageConfig {
|
|
402
|
-
apiKey: string;
|
|
403
|
-
debug?: boolean;
|
|
404
|
-
modules?: ModuleName[];
|
|
405
|
-
baseUrl?: string;
|
|
406
|
-
timeout?: number;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
// 자동완성 및 타입 검사
|
|
410
|
-
AdStage.ads.banner('container', {
|
|
411
|
-
width: '100%', // ✅ string | number
|
|
412
|
-
height: 250, // ✅ number
|
|
413
|
-
autoSlide: true // ✅ boolean
|
|
414
|
-
});
|
|
415
155
|
```
|
|
416
156
|
|
|
417
|
-
###
|
|
418
|
-
`await` 없이 즉시 사용 가능한 동기 API로 설계되어 개발이 간편합니다.
|
|
157
|
+
### Ad Rendering (with options)
|
|
419
158
|
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
AdStage.
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
// ❌ 비동기 - 복잡한 처리 필요
|
|
426
|
-
await AdStage.init({ apiKey: 'key' });
|
|
427
|
-
const id = await AdStage.ads.banner('container');
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
## 📊 번들 크기 & 성능
|
|
431
|
-
|
|
432
|
-
### 최적화된 번들 크기
|
|
433
|
-
```
|
|
434
|
-
dist/
|
|
435
|
-
├── index.esm.js # ES 모듈 (28KB gzipped)
|
|
436
|
-
├── index.cjs.js # CommonJS (30KB gzipped)
|
|
437
|
-
├── index.umd.js # UMD 브라우저 (32KB gzipped)
|
|
438
|
-
└── index.d.ts # TypeScript 타입 정의
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
### Tree Shaking 지원
|
|
442
|
-
ES 모듈 형태로 제공되어 번들러의 tree shaking으로 사용하지 않는 코드 제거가 가능합니다.
|
|
443
|
-
|
|
444
|
-
```typescript
|
|
445
|
-
// 필요한 모듈만 임포트
|
|
446
|
-
import { AdStage } from '@adstage/web-sdk';
|
|
447
|
-
|
|
448
|
-
// 특정 타입만 임포트
|
|
449
|
-
import type { AdStageConfig, AdOptions } from '@adstage/web-sdk';
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
### Lazy 로딩 시스템
|
|
453
|
-
광고 콘텐츠는 백그라운드에서 로드되어 사용자 경험을 향상시킵니다.
|
|
454
|
-
|
|
455
|
-
```typescript
|
|
456
|
-
// 1. 즉시 placeholder 표시
|
|
457
|
-
const id = AdStage.ads.banner('container');
|
|
458
|
-
|
|
459
|
-
// 2. 백그라운드에서 광고 로드
|
|
460
|
-
// 3. 로드 완료 시 실제 광고로 교체
|
|
159
|
+
```javascript
|
|
160
|
+
AdStage.ads.banner('container-id', { width: '100%', height: 250 });
|
|
161
|
+
AdStage.ads.text('container-id', { maxLines: 3 });
|
|
162
|
+
AdStage.ads.video('container-id', { width: 640, height: 360, autoplay: false });
|
|
461
163
|
```
|
|
462
164
|
|
|
463
|
-
|
|
165
|
+
### Ad Options Table
|
|
464
166
|
|
|
465
|
-
|
|
466
|
-
- **ES 모듈**: ES2018+ 지원 브라우저
|
|
467
|
-
- **폴리필**: 필요시 별도 제공
|
|
468
|
-
- **SSR 안전**: Next.js, Nuxt.js 등 SSR 프레임워크 지원
|
|
167
|
+
#### Banner
|
|
469
168
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
169
|
+
| Option | Type | Default | Description |
|
|
170
|
+
| -------------- | ----------- | -------- | -------------------------- |
|
|
171
|
+
| `width` | `string | number` | `'100%'` |
|
|
172
|
+
| `height` | `number` | `250` | Height (px) |
|
|
173
|
+
| `position` | `'top' | 'bottom' | 'center'` |
|
|
174
|
+
| `responsive` | `boolean` | `true` | Enable responsive resizing |
|
|
476
175
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
### ✅ 완료된 기능
|
|
480
|
-
- [x] **네임스페이스 아키텍처** - 충돌 방지 및 체계적 구조
|
|
481
|
-
- [x] **동기 초기화 시스템** - `await` 없는 즉시 사용 가능
|
|
482
|
-
- [x] **광고 모듈 (AdsModule)** - 5가지 광고 타입 완전 구현
|
|
483
|
-
- [x] 배너, 텍스트, 비디오, 네이티브, 전면 광고
|
|
484
|
-
- [x] 자동 슬라이더 및 페이드 효과
|
|
485
|
-
- [x] Lazy 로딩 시스템
|
|
486
|
-
- [x] 이벤트 추적 및 중복 방지
|
|
487
|
-
- [x] **설정 모듈 (ConfigModule)** - 동기 설정 관리
|
|
488
|
-
- [x] 환경 자동 감지
|
|
489
|
-
- [x] 런타임 설정 변경
|
|
490
|
-
- [x] 모듈 선택적 로딩
|
|
491
|
-
- [x] **TypeScript 타입 정의** - 완전한 타입 안전성
|
|
492
|
-
- [x] **다중 빌드 타겟** - ESM/CJS/UMD 지원
|
|
493
|
-
- [x] **SSR 지원** - Next.js, Nuxt.js 등 호환
|
|
494
|
-
|
|
495
|
-
### 🚧 기본 구조 완성 (향후 구현)
|
|
496
|
-
- [ ] **이벤트 모듈 (EventsModule)** - Q1 2025 구현 예정
|
|
497
|
-
- [x] 기본 인터페이스 및 메소드 구조
|
|
498
|
-
- [ ] 실제 서버 통신 로직
|
|
499
|
-
- [ ] 배치 처리 시스템
|
|
500
|
-
- [ ] 오프라인 지원
|
|
501
|
-
|
|
502
|
-
### 📋 다음 단계
|
|
503
|
-
1. **Q1 2025**: EventsModule 완전 구현
|
|
504
|
-
2. **Q2 2025**: 성능 최적화 및 고급 타겟팅
|
|
505
|
-
3. **Q3 2025**: A/B 테스트 및 개인화 기능
|
|
506
|
-
|
|
507
|
-
## 🛠 개발 가이드
|
|
508
|
-
|
|
509
|
-
### 프로젝트 구조
|
|
510
|
-
```
|
|
511
|
-
src/
|
|
512
|
-
├── core/
|
|
513
|
-
│ └── AdStage.ts # 메인 네임스페이스 클래스
|
|
514
|
-
├── modules/
|
|
515
|
-
│ ├── ads/ # ✅ 광고 모듈 (완전 구현)
|
|
516
|
-
│ │ └── AdsModule.ts
|
|
517
|
-
│ ├── config/ # ✅ 설정 모듈 (완전 구현)
|
|
518
|
-
│ │ └── ConfigModule.ts
|
|
519
|
-
│ └── events/ # 🚧 이벤트 모듈 (기본 구조)
|
|
520
|
-
│ └── EventsModule.ts
|
|
521
|
-
├── managers/ # 기능별 관리 클래스
|
|
522
|
-
│ ├── event-tracker.ts # 이벤트 추적
|
|
523
|
-
│ ├── impression-tracker.ts # 중복 노출 방지
|
|
524
|
-
│ ├── carousel-slider-manager.ts # 슬라이더 관리
|
|
525
|
-
│ └── text-transition-manager.ts # 텍스트 전환 효과
|
|
526
|
-
├── types/ # TypeScript 타입 정의
|
|
527
|
-
│ ├── config.ts # SDK 설정 타입
|
|
528
|
-
│ ├── advertisement.ts # 광고 관련 타입
|
|
529
|
-
│ ├── events.ts # 이벤트 관련 타입
|
|
530
|
-
│ └── api.ts # API 응답 타입
|
|
531
|
-
├── utils/ # 유틸리티 함수
|
|
532
|
-
│ ├── sdk-utils.ts # SDK 공통 유틸
|
|
533
|
-
│ ├── dom-utils.ts # DOM 조작 유틸
|
|
534
|
-
│ └── api-headers.ts # API 헤더 생성
|
|
535
|
-
├── constants/
|
|
536
|
-
│ └── endpoints.ts # API 엔드포인트 관리
|
|
537
|
-
└── index.ts # 메인 익스포트
|
|
538
|
-
```
|
|
176
|
+
#### Text
|
|
539
177
|
|
|
540
|
-
|
|
178
|
+
| Option | Type | Default | Description |
|
|
179
|
+
| ------------- | ---------- | -------- | ----------------- |
|
|
180
|
+
| `maxLines` | `number` | `3` | Max visible lines |
|
|
181
|
+
| `fontSize` | `number` | `14` | Font size (px) |
|
|
182
|
+
| `textAlign` | `'left' | 'center' | 'right'` |
|
|
541
183
|
|
|
542
|
-
|
|
543
|
-
# 의존성 설치
|
|
544
|
-
pnpm install
|
|
184
|
+
#### Video
|
|
545
185
|
|
|
546
|
-
|
|
547
|
-
|
|
186
|
+
| Option | Type | Default | Description |
|
|
187
|
+
| ------------ | ----------- | --------- | -------------------------------------- |
|
|
188
|
+
| `width` | `number` | `640` | Video width (px) |
|
|
189
|
+
| `height` | `number` | `360` | Video height (px) |
|
|
190
|
+
| `autoplay` | `boolean` | `false` | Auto play on load |
|
|
191
|
+
| `muted` | `boolean` | `true` | Start muted (recommended for autoplay) |
|
|
192
|
+
| `controls` | `boolean` | `true` | Show native controls |
|
|
193
|
+
| `loop` | `boolean` | `false` | Loop playback |
|
|
548
194
|
|
|
549
|
-
|
|
550
|
-
pnpm run lint
|
|
195
|
+
## 📚 API Reference
|
|
551
196
|
|
|
552
|
-
|
|
553
|
-
pnpm run build
|
|
554
|
-
```
|
|
197
|
+
### Core (Common)
|
|
555
198
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
199
|
+
| Function | Description | Params | Returns | Example |
|
|
200
|
+
| ------------- | --------------------------- | --------------------------------------- | ----------- | ----------------------------------- |
|
|
201
|
+
| `init()` | Initialize SDK (required) | `{ apiKey: string, debug?: boolean }` | `void` | `AdStage.init({ apiKey: 'key' })` |
|
|
202
|
+
| `isReady()` | Check initialization status | - | `boolean` | `AdStage.isReady()` |
|
|
203
|
+
| `reset()` | Reset state (testing) | - | `void` | `AdStage.reset()` |
|
|
561
204
|
|
|
562
|
-
###
|
|
563
|
-
- **TypeScript strict 모드** 활성화
|
|
564
|
-
- **ESLint + Prettier** 자동 포맷팅
|
|
565
|
-
- **JSDoc 주석** 모든 public API에 필수
|
|
566
|
-
- **에러 처리** 모든 async 함수에 try-catch
|
|
205
|
+
### Ads Module (`AdStage.ads`)
|
|
567
206
|
|
|
568
|
-
|
|
207
|
+
| Function | Description | Params | Returns | Example |
|
|
208
|
+
| ------------ | ---------------- | ------------------------- | ----------------- | ------------------------------ |
|
|
209
|
+
| `banner()` | Render banner ad | `containerId, options?` | `Promise<void>` | `AdStage.ads.banner('slot')` |
|
|
210
|
+
| `text()` | Render text ad | `containerId, options?` | `Promise<void>` | `AdStage.ads.text('slot')` |
|
|
211
|
+
| `video()` | Render video ad | `containerId, options?` | `Promise<void>` | `AdStage.ads.video('slot')` |
|
|
569
212
|
|
|
570
|
-
###
|
|
571
|
-
이슈를 발견하셨다면 다음 정보와 함께 GitHub Issues에 신고해 주세요:
|
|
213
|
+
### Events Module (`AdStage.events`)
|
|
572
214
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
-
|
|
215
|
+
| Function | Description | Params | Returns | Example |
|
|
216
|
+
| ----------------------- | ------------------- | --------------------- | ----------------- | ------------------------------------------------------- |
|
|
217
|
+
| `track()` | Track an event | `name, properties?` | `Promise<void>` | `AdStage.events.track('click')` |
|
|
218
|
+
| `setUserId()` | Set user ID | `userId` | `void` | `AdStage.events.setUserId('u1')` |
|
|
219
|
+
| `getUserId()` | Get user ID | - | `string | null` |
|
|
220
|
+
| `setUserProperties()` | Set user attributes | `UserProperties` | `void` | `AdStage.events.setUserProperties({ country: 'KR' })` |
|
|
221
|
+
| `getUserProperties()` | Get user attributes | - | `UserProperties | null` |
|
|
578
222
|
|
|
579
|
-
|
|
580
|
-
새로운 기능이나 개선사항이 있다면 제안해 주세요:
|
|
223
|
+
#### UserProperties
|
|
581
224
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
225
|
+
| Field | Type | Description | Example |
|
|
226
|
+
| ------------ | ---------- | ----------------------- | ----------- |
|
|
227
|
+
| `gender` | `string` | Gender | `'male'` |
|
|
228
|
+
| `country` | `string` | ISO 3166-1 country code | `'KR'` |
|
|
229
|
+
| `city` | `string` | City name | `'Seoul'` |
|
|
230
|
+
| `age` | `string` | Age band or value | `'20-29'` |
|
|
231
|
+
| `language` | `string` | ISO 639-1 language code | `'en'` |
|
|
585
232
|
|
|
586
|
-
###
|
|
233
|
+
### Global Helper Functions
|
|
587
234
|
|
|
588
|
-
|
|
589
|
-
# 1. 포크 및 클론
|
|
590
|
-
git clone https://github.com/your-username/adstage.git
|
|
591
|
-
cd adstage/sdk
|
|
235
|
+
Firebase‑style named exports. Equivalent to `AdStage.events.*`.
|
|
592
236
|
|
|
593
|
-
|
|
594
|
-
|
|
237
|
+
| Function | Description | Equivalent |
|
|
238
|
+
| ----------------------- | ------------------- | -------------------------------------- |
|
|
239
|
+
| `track()` | Track event | `AdStage.events.track()` |
|
|
240
|
+
| `setUserId()` | Set user ID | `AdStage.events.setUserId()` |
|
|
241
|
+
| `getUserId()` | Get user ID | `AdStage.events.getUserId()` |
|
|
242
|
+
| `setUserProperties()` | Set user attributes | `AdStage.events.setUserProperties()` |
|
|
243
|
+
| `getUserProperties()` | Get user attributes | `AdStage.events.getUserProperties()` |
|
|
595
244
|
|
|
596
|
-
|
|
597
|
-
git checkout -b feature/amazing-feature
|
|
245
|
+
### React Components & Hooks
|
|
598
246
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
247
|
+
| Name | Type | Returns | Purpose |
|
|
248
|
+
| ---------------------- | --------- | ------------------------------------ | ----------------------- |
|
|
249
|
+
| `AdStageProvider` | Component | - | Provide SDK via context |
|
|
250
|
+
| `useAdStageInstance` | Hook | `AdStage | null` |
|
|
251
|
+
| `useAdStageContext` | Hook | `{ isInitialized, config, error }` | State / error handling |
|
|
603
252
|
|
|
604
|
-
|
|
605
|
-
git commit -m '✨ Add amazing feature'
|
|
606
|
-
git push origin feature/amazing-feature
|
|
253
|
+
#### Hook Usage
|
|
607
254
|
|
|
608
|
-
|
|
255
|
+
```jsx
|
|
256
|
+
const adstage = useAdStageInstance();
|
|
257
|
+
adstage?.events.track('click', { button: 'cta' });
|
|
609
258
|
```
|
|
610
259
|
|
|
611
|
-
## 📄
|
|
612
|
-
|
|
613
|
-
MIT License © 2024 AdStage
|
|
614
|
-
|
|
615
|
-
자세한 내용은 [LICENSE](./LICENSE) 파일을 참조하세요.
|
|
616
|
-
|
|
617
|
-
## 🔗 링크
|
|
618
|
-
|
|
619
|
-
- [📖 공식 문서](https://docs.adstage.io)
|
|
620
|
-
- [🐛 이슈 신고](https://github.com/nbase-io/adstage/issues)
|
|
621
|
-
- [💬 디스커션](https://github.com/nbase-io/adstage/discussions)
|
|
622
|
-
- [📦 NPM 패키지](https://www.npmjs.com/package/@adstage/web-sdk)
|
|
623
|
-
|
|
624
|
-
---
|
|
260
|
+
## 📄 License
|
|
625
261
|
|
|
626
|
-
|
|
262
|
+
MIT License © 2025 stageUp
|