@adstage/web-sdk 2.4.5 → 2.4.6
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/dist/index.cjs.js +34 -7
- package/dist/index.esm.js +34 -7
- package/dist/index.standalone.js +34 -7
- package/package.json +1 -1
- package/src/managers/ads/viewable-event-tracker.ts +37 -7
package/dist/index.cjs.js
CHANGED
|
@@ -47,11 +47,15 @@ class ViewableEventTracker {
|
|
|
47
47
|
static isDuplicateViewable(adId, slotId, debug = false) {
|
|
48
48
|
const key = `${adId}_${slotId}`;
|
|
49
49
|
const now = Date.now();
|
|
50
|
+
// 디버그 모드에 따른 쿨다운 시간 결정
|
|
51
|
+
const cooldownTime = debug ?
|
|
52
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_DEBUG :
|
|
53
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_PRODUCTION;
|
|
50
54
|
// 메모리 기반 중복 확인 (새로고침 시 초기화됨)
|
|
51
55
|
const lastViewable = ViewableEventTracker.viewableTracker.get(key);
|
|
52
|
-
if (lastViewable && (now - lastViewable) <
|
|
56
|
+
if (lastViewable && (now - lastViewable) < cooldownTime) {
|
|
53
57
|
if (debug) {
|
|
54
|
-
console.log(`Duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((
|
|
58
|
+
console.log(`Duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((cooldownTime - (now - lastViewable)) / 1000)}s remaining (${debug ? 'debug' : 'production'} mode)`);
|
|
55
59
|
}
|
|
56
60
|
return true;
|
|
57
61
|
}
|
|
@@ -60,9 +64,9 @@ class ViewableEventTracker {
|
|
|
60
64
|
const sessionViewable = sessionStorage.getItem(sessionKey);
|
|
61
65
|
if (sessionViewable) {
|
|
62
66
|
const sessionTime = parseInt(sessionViewable, 10);
|
|
63
|
-
if (!isNaN(sessionTime) && (now - sessionTime) <
|
|
67
|
+
if (!isNaN(sessionTime) && (now - sessionTime) < cooldownTime) {
|
|
64
68
|
if (debug) {
|
|
65
|
-
console.log(`Session-based duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((
|
|
69
|
+
console.log(`Session-based duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((cooldownTime - (now - sessionTime)) / 1000)}s remaining (${debug ? 'debug' : 'production'} mode)`);
|
|
66
70
|
}
|
|
67
71
|
// 메모리에도 기록하여 이후 요청 최적화
|
|
68
72
|
ViewableEventTracker.viewableTracker.set(key, sessionTime);
|
|
@@ -74,6 +78,9 @@ class ViewableEventTracker {
|
|
|
74
78
|
sessionStorage.setItem(sessionKey, now.toString());
|
|
75
79
|
// 오래된 세션 스토리지 데이터 정리 (선택적)
|
|
76
80
|
ViewableEventTracker.cleanupOldViewables();
|
|
81
|
+
if (debug) {
|
|
82
|
+
console.log(`✅ New viewable recorded for ad ${adId} in slot ${slotId} (${debug ? 'debug' : 'production'} mode)`);
|
|
83
|
+
}
|
|
77
84
|
return false;
|
|
78
85
|
}
|
|
79
86
|
/**
|
|
@@ -81,7 +88,8 @@ class ViewableEventTracker {
|
|
|
81
88
|
*/
|
|
82
89
|
static cleanupOldViewables() {
|
|
83
90
|
const now = Date.now();
|
|
84
|
-
|
|
91
|
+
// 프로덕션 쿨다운의 2배 시간이 지난 데이터 정리
|
|
92
|
+
const cleanupThreshold = ViewableEventTracker.VIEWABLE_COOLDOWN_PRODUCTION * 2;
|
|
85
93
|
// 세션 스토리지 정리
|
|
86
94
|
for (let i = 0; i < sessionStorage.length; i++) {
|
|
87
95
|
const key = sessionStorage.key(i);
|
|
@@ -104,14 +112,33 @@ class ViewableEventTracker {
|
|
|
104
112
|
}
|
|
105
113
|
}
|
|
106
114
|
/**
|
|
107
|
-
* 모든 추적 데이터 정리
|
|
115
|
+
* 모든 추적 데이터 정리 (디버그용)
|
|
108
116
|
*/
|
|
109
117
|
static clear() {
|
|
110
118
|
ViewableEventTracker.viewableTracker.clear();
|
|
119
|
+
// 세션 스토리지에서도 adstage_viewable_ 키들 제거
|
|
120
|
+
const keysToRemove = [];
|
|
121
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
|
122
|
+
const key = sessionStorage.key(i);
|
|
123
|
+
if (key && key.startsWith('adstage_viewable_')) {
|
|
124
|
+
keysToRemove.push(key);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
keysToRemove.forEach(key => sessionStorage.removeItem(key));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* 특정 광고의 viewable 추적 초기화 (디버그용)
|
|
131
|
+
*/
|
|
132
|
+
static clearAdViewable(adId, slotId) {
|
|
133
|
+
const key = `${adId}_${slotId}`;
|
|
134
|
+
ViewableEventTracker.viewableTracker.delete(key);
|
|
135
|
+
const sessionKey = `adstage_viewable_${key}`;
|
|
136
|
+
sessionStorage.removeItem(sessionKey);
|
|
111
137
|
}
|
|
112
138
|
}
|
|
113
139
|
ViewableEventTracker.viewableTracker = new Map();
|
|
114
|
-
ViewableEventTracker.
|
|
140
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_PRODUCTION = 300000; // 5분 쿨다운 (프로덕션)
|
|
141
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_DEBUG = 30000; // 30초 쿨다운 (디버그)
|
|
115
142
|
|
|
116
143
|
/**
|
|
117
144
|
* SSR 안전한 DOM API 래퍼 클래스
|
package/dist/index.esm.js
CHANGED
|
@@ -45,11 +45,15 @@ class ViewableEventTracker {
|
|
|
45
45
|
static isDuplicateViewable(adId, slotId, debug = false) {
|
|
46
46
|
const key = `${adId}_${slotId}`;
|
|
47
47
|
const now = Date.now();
|
|
48
|
+
// 디버그 모드에 따른 쿨다운 시간 결정
|
|
49
|
+
const cooldownTime = debug ?
|
|
50
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_DEBUG :
|
|
51
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_PRODUCTION;
|
|
48
52
|
// 메모리 기반 중복 확인 (새로고침 시 초기화됨)
|
|
49
53
|
const lastViewable = ViewableEventTracker.viewableTracker.get(key);
|
|
50
|
-
if (lastViewable && (now - lastViewable) <
|
|
54
|
+
if (lastViewable && (now - lastViewable) < cooldownTime) {
|
|
51
55
|
if (debug) {
|
|
52
|
-
console.log(`Duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((
|
|
56
|
+
console.log(`Duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((cooldownTime - (now - lastViewable)) / 1000)}s remaining (${debug ? 'debug' : 'production'} mode)`);
|
|
53
57
|
}
|
|
54
58
|
return true;
|
|
55
59
|
}
|
|
@@ -58,9 +62,9 @@ class ViewableEventTracker {
|
|
|
58
62
|
const sessionViewable = sessionStorage.getItem(sessionKey);
|
|
59
63
|
if (sessionViewable) {
|
|
60
64
|
const sessionTime = parseInt(sessionViewable, 10);
|
|
61
|
-
if (!isNaN(sessionTime) && (now - sessionTime) <
|
|
65
|
+
if (!isNaN(sessionTime) && (now - sessionTime) < cooldownTime) {
|
|
62
66
|
if (debug) {
|
|
63
|
-
console.log(`Session-based duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((
|
|
67
|
+
console.log(`Session-based duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((cooldownTime - (now - sessionTime)) / 1000)}s remaining (${debug ? 'debug' : 'production'} mode)`);
|
|
64
68
|
}
|
|
65
69
|
// 메모리에도 기록하여 이후 요청 최적화
|
|
66
70
|
ViewableEventTracker.viewableTracker.set(key, sessionTime);
|
|
@@ -72,6 +76,9 @@ class ViewableEventTracker {
|
|
|
72
76
|
sessionStorage.setItem(sessionKey, now.toString());
|
|
73
77
|
// 오래된 세션 스토리지 데이터 정리 (선택적)
|
|
74
78
|
ViewableEventTracker.cleanupOldViewables();
|
|
79
|
+
if (debug) {
|
|
80
|
+
console.log(`✅ New viewable recorded for ad ${adId} in slot ${slotId} (${debug ? 'debug' : 'production'} mode)`);
|
|
81
|
+
}
|
|
75
82
|
return false;
|
|
76
83
|
}
|
|
77
84
|
/**
|
|
@@ -79,7 +86,8 @@ class ViewableEventTracker {
|
|
|
79
86
|
*/
|
|
80
87
|
static cleanupOldViewables() {
|
|
81
88
|
const now = Date.now();
|
|
82
|
-
|
|
89
|
+
// 프로덕션 쿨다운의 2배 시간이 지난 데이터 정리
|
|
90
|
+
const cleanupThreshold = ViewableEventTracker.VIEWABLE_COOLDOWN_PRODUCTION * 2;
|
|
83
91
|
// 세션 스토리지 정리
|
|
84
92
|
for (let i = 0; i < sessionStorage.length; i++) {
|
|
85
93
|
const key = sessionStorage.key(i);
|
|
@@ -102,14 +110,33 @@ class ViewableEventTracker {
|
|
|
102
110
|
}
|
|
103
111
|
}
|
|
104
112
|
/**
|
|
105
|
-
* 모든 추적 데이터 정리
|
|
113
|
+
* 모든 추적 데이터 정리 (디버그용)
|
|
106
114
|
*/
|
|
107
115
|
static clear() {
|
|
108
116
|
ViewableEventTracker.viewableTracker.clear();
|
|
117
|
+
// 세션 스토리지에서도 adstage_viewable_ 키들 제거
|
|
118
|
+
const keysToRemove = [];
|
|
119
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
|
120
|
+
const key = sessionStorage.key(i);
|
|
121
|
+
if (key && key.startsWith('adstage_viewable_')) {
|
|
122
|
+
keysToRemove.push(key);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
keysToRemove.forEach(key => sessionStorage.removeItem(key));
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* 특정 광고의 viewable 추적 초기화 (디버그용)
|
|
129
|
+
*/
|
|
130
|
+
static clearAdViewable(adId, slotId) {
|
|
131
|
+
const key = `${adId}_${slotId}`;
|
|
132
|
+
ViewableEventTracker.viewableTracker.delete(key);
|
|
133
|
+
const sessionKey = `adstage_viewable_${key}`;
|
|
134
|
+
sessionStorage.removeItem(sessionKey);
|
|
109
135
|
}
|
|
110
136
|
}
|
|
111
137
|
ViewableEventTracker.viewableTracker = new Map();
|
|
112
|
-
ViewableEventTracker.
|
|
138
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_PRODUCTION = 300000; // 5분 쿨다운 (프로덕션)
|
|
139
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_DEBUG = 30000; // 30초 쿨다운 (디버그)
|
|
113
140
|
|
|
114
141
|
/**
|
|
115
142
|
* SSR 안전한 DOM API 래퍼 클래스
|
package/dist/index.standalone.js
CHANGED
|
@@ -42,11 +42,15 @@ class ViewableEventTracker {
|
|
|
42
42
|
static isDuplicateViewable(adId, slotId, debug = false) {
|
|
43
43
|
const key = `${adId}_${slotId}`;
|
|
44
44
|
const now = Date.now();
|
|
45
|
+
// 디버그 모드에 따른 쿨다운 시간 결정
|
|
46
|
+
const cooldownTime = debug ?
|
|
47
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_DEBUG :
|
|
48
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_PRODUCTION;
|
|
45
49
|
// 메모리 기반 중복 확인 (새로고침 시 초기화됨)
|
|
46
50
|
const lastViewable = ViewableEventTracker.viewableTracker.get(key);
|
|
47
|
-
if (lastViewable && (now - lastViewable) <
|
|
51
|
+
if (lastViewable && (now - lastViewable) < cooldownTime) {
|
|
48
52
|
if (debug) {
|
|
49
|
-
console.log(`Duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((
|
|
53
|
+
console.log(`Duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((cooldownTime - (now - lastViewable)) / 1000)}s remaining (${debug ? 'debug' : 'production'} mode)`);
|
|
50
54
|
}
|
|
51
55
|
return true;
|
|
52
56
|
}
|
|
@@ -55,9 +59,9 @@ class ViewableEventTracker {
|
|
|
55
59
|
const sessionViewable = sessionStorage.getItem(sessionKey);
|
|
56
60
|
if (sessionViewable) {
|
|
57
61
|
const sessionTime = parseInt(sessionViewable, 10);
|
|
58
|
-
if (!isNaN(sessionTime) && (now - sessionTime) <
|
|
62
|
+
if (!isNaN(sessionTime) && (now - sessionTime) < cooldownTime) {
|
|
59
63
|
if (debug) {
|
|
60
|
-
console.log(`Session-based duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((
|
|
64
|
+
console.log(`Session-based duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((cooldownTime - (now - sessionTime)) / 1000)}s remaining (${debug ? 'debug' : 'production'} mode)`);
|
|
61
65
|
}
|
|
62
66
|
// 메모리에도 기록하여 이후 요청 최적화
|
|
63
67
|
ViewableEventTracker.viewableTracker.set(key, sessionTime);
|
|
@@ -69,6 +73,9 @@ class ViewableEventTracker {
|
|
|
69
73
|
sessionStorage.setItem(sessionKey, now.toString());
|
|
70
74
|
// 오래된 세션 스토리지 데이터 정리 (선택적)
|
|
71
75
|
ViewableEventTracker.cleanupOldViewables();
|
|
76
|
+
if (debug) {
|
|
77
|
+
console.log(`✅ New viewable recorded for ad ${adId} in slot ${slotId} (${debug ? 'debug' : 'production'} mode)`);
|
|
78
|
+
}
|
|
72
79
|
return false;
|
|
73
80
|
}
|
|
74
81
|
/**
|
|
@@ -76,7 +83,8 @@ class ViewableEventTracker {
|
|
|
76
83
|
*/
|
|
77
84
|
static cleanupOldViewables() {
|
|
78
85
|
const now = Date.now();
|
|
79
|
-
|
|
86
|
+
// 프로덕션 쿨다운의 2배 시간이 지난 데이터 정리
|
|
87
|
+
const cleanupThreshold = ViewableEventTracker.VIEWABLE_COOLDOWN_PRODUCTION * 2;
|
|
80
88
|
// 세션 스토리지 정리
|
|
81
89
|
for (let i = 0; i < sessionStorage.length; i++) {
|
|
82
90
|
const key = sessionStorage.key(i);
|
|
@@ -99,14 +107,33 @@ class ViewableEventTracker {
|
|
|
99
107
|
}
|
|
100
108
|
}
|
|
101
109
|
/**
|
|
102
|
-
* 모든 추적 데이터 정리
|
|
110
|
+
* 모든 추적 데이터 정리 (디버그용)
|
|
103
111
|
*/
|
|
104
112
|
static clear() {
|
|
105
113
|
ViewableEventTracker.viewableTracker.clear();
|
|
114
|
+
// 세션 스토리지에서도 adstage_viewable_ 키들 제거
|
|
115
|
+
const keysToRemove = [];
|
|
116
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
|
117
|
+
const key = sessionStorage.key(i);
|
|
118
|
+
if (key && key.startsWith('adstage_viewable_')) {
|
|
119
|
+
keysToRemove.push(key);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
keysToRemove.forEach(key => sessionStorage.removeItem(key));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 특정 광고의 viewable 추적 초기화 (디버그용)
|
|
126
|
+
*/
|
|
127
|
+
static clearAdViewable(adId, slotId) {
|
|
128
|
+
const key = `${adId}_${slotId}`;
|
|
129
|
+
ViewableEventTracker.viewableTracker.delete(key);
|
|
130
|
+
const sessionKey = `adstage_viewable_${key}`;
|
|
131
|
+
sessionStorage.removeItem(sessionKey);
|
|
106
132
|
}
|
|
107
133
|
}
|
|
108
134
|
ViewableEventTracker.viewableTracker = new Map();
|
|
109
|
-
ViewableEventTracker.
|
|
135
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_PRODUCTION = 300000; // 5분 쿨다운 (프로덕션)
|
|
136
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_DEBUG = 30000; // 30초 쿨다운 (디버그)
|
|
110
137
|
|
|
111
138
|
/**
|
|
112
139
|
* SSR 안전한 DOM API 래퍼 클래스
|
package/package.json
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export class ViewableEventTracker {
|
|
9
9
|
private static viewableTracker = new Map<string, number>();
|
|
10
|
-
private static readonly
|
|
10
|
+
private static readonly VIEWABLE_COOLDOWN_PRODUCTION = 300000; // 5분 쿨다운 (프로덕션)
|
|
11
|
+
private static readonly VIEWABLE_COOLDOWN_DEBUG = 30000; // 30초 쿨다운 (디버그)
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* 중복 viewable 이벤트 여부 확인
|
|
@@ -16,11 +17,16 @@ export class ViewableEventTracker {
|
|
|
16
17
|
const key = `${adId}_${slotId}`;
|
|
17
18
|
const now = Date.now();
|
|
18
19
|
|
|
20
|
+
// 디버그 모드에 따른 쿨다운 시간 결정
|
|
21
|
+
const cooldownTime = debug ?
|
|
22
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_DEBUG :
|
|
23
|
+
ViewableEventTracker.VIEWABLE_COOLDOWN_PRODUCTION;
|
|
24
|
+
|
|
19
25
|
// 메모리 기반 중복 확인 (새로고침 시 초기화됨)
|
|
20
26
|
const lastViewable = ViewableEventTracker.viewableTracker.get(key);
|
|
21
|
-
if (lastViewable && (now - lastViewable) <
|
|
27
|
+
if (lastViewable && (now - lastViewable) < cooldownTime) {
|
|
22
28
|
if (debug) {
|
|
23
|
-
console.log(`Duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((
|
|
29
|
+
console.log(`Duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((cooldownTime - (now - lastViewable)) / 1000)}s remaining (${debug ? 'debug' : 'production'} mode)`);
|
|
24
30
|
}
|
|
25
31
|
return true;
|
|
26
32
|
}
|
|
@@ -30,9 +36,9 @@ export class ViewableEventTracker {
|
|
|
30
36
|
const sessionViewable = sessionStorage.getItem(sessionKey);
|
|
31
37
|
if (sessionViewable) {
|
|
32
38
|
const sessionTime = parseInt(sessionViewable, 10);
|
|
33
|
-
if (!isNaN(sessionTime) && (now - sessionTime) <
|
|
39
|
+
if (!isNaN(sessionTime) && (now - sessionTime) < cooldownTime) {
|
|
34
40
|
if (debug) {
|
|
35
|
-
console.log(`Session-based duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((
|
|
41
|
+
console.log(`Session-based duplicate viewable blocked for ad ${adId} in slot ${slotId}. Cooldown: ${Math.round((cooldownTime - (now - sessionTime)) / 1000)}s remaining (${debug ? 'debug' : 'production'} mode)`);
|
|
36
42
|
}
|
|
37
43
|
// 메모리에도 기록하여 이후 요청 최적화
|
|
38
44
|
ViewableEventTracker.viewableTracker.set(key, sessionTime);
|
|
@@ -47,6 +53,10 @@ export class ViewableEventTracker {
|
|
|
47
53
|
// 오래된 세션 스토리지 데이터 정리 (선택적)
|
|
48
54
|
ViewableEventTracker.cleanupOldViewables();
|
|
49
55
|
|
|
56
|
+
if (debug) {
|
|
57
|
+
console.log(`✅ New viewable recorded for ad ${adId} in slot ${slotId} (${debug ? 'debug' : 'production'} mode)`);
|
|
58
|
+
}
|
|
59
|
+
|
|
50
60
|
return false;
|
|
51
61
|
}
|
|
52
62
|
|
|
@@ -55,7 +65,8 @@ export class ViewableEventTracker {
|
|
|
55
65
|
*/
|
|
56
66
|
private static cleanupOldViewables(): void {
|
|
57
67
|
const now = Date.now();
|
|
58
|
-
|
|
68
|
+
// 프로덕션 쿨다운의 2배 시간이 지난 데이터 정리
|
|
69
|
+
const cleanupThreshold = ViewableEventTracker.VIEWABLE_COOLDOWN_PRODUCTION * 2;
|
|
59
70
|
|
|
60
71
|
// 세션 스토리지 정리
|
|
61
72
|
for (let i = 0; i < sessionStorage.length; i++) {
|
|
@@ -81,9 +92,28 @@ export class ViewableEventTracker {
|
|
|
81
92
|
}
|
|
82
93
|
|
|
83
94
|
/**
|
|
84
|
-
* 모든 추적 데이터 정리
|
|
95
|
+
* 모든 추적 데이터 정리 (디버그용)
|
|
85
96
|
*/
|
|
86
97
|
static clear(): void {
|
|
87
98
|
ViewableEventTracker.viewableTracker.clear();
|
|
99
|
+
// 세션 스토리지에서도 adstage_viewable_ 키들 제거
|
|
100
|
+
const keysToRemove: string[] = [];
|
|
101
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
|
102
|
+
const key = sessionStorage.key(i);
|
|
103
|
+
if (key && key.startsWith('adstage_viewable_')) {
|
|
104
|
+
keysToRemove.push(key);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
keysToRemove.forEach(key => sessionStorage.removeItem(key));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 특정 광고의 viewable 추적 초기화 (디버그용)
|
|
112
|
+
*/
|
|
113
|
+
static clearAdViewable(adId: string, slotId: string): void {
|
|
114
|
+
const key = `${adId}_${slotId}`;
|
|
115
|
+
ViewableEventTracker.viewableTracker.delete(key);
|
|
116
|
+
const sessionKey = `adstage_viewable_${key}`;
|
|
117
|
+
sessionStorage.removeItem(sessionKey);
|
|
88
118
|
}
|
|
89
119
|
}
|