Vinc3nt's Life

POC - Solution to integrate iframe with ads featured

2024-03-30
develop
iframe
ads
research
最後更新:2025-01-26
4分鐘
650字

Purpose

使用者可以 iframe snippet,直接無痛使用 SDK

  • 可以使用 vast 廣告播放相關的功能
  • 可以動態調整部分 video player 參數

Research

HTML iframe

iframe 是 HTML 中的一個元素,通常用來嵌套另一個 HTML 文檔。 如果想要向 iframe 傳遞參數,有以下方法可以實現這個目的:

URL 參數

通過在 iframe 的 src URL 中添加查詢字符串參數,可以將參數傳遞給目標文檔。目標文檔可以使用 JavaScript 來解析這些參數。

1
<iframe src="https://example.com/page.html?param1=value1&param2=value2"></iframe>

在目標文檔中,可以使用 JavaScript 的 URLSearchParams 接口來獲取這些參數:

1
let params = new URLSearchParams(window.location.search);
2
let param1 = params.get('param1');
3
let param2 = params.get('param2');

窗口消息

使用 window.postMessage 方法在來源和目標窗口之間傳遞消息。這是一種在不同的源之間安全傳遞數據的方法。

1
let iframe = document.getElementById('your-iframe-id');
2
iframe.contentWindow.postMessage('Your message here', 'https://target-origin.com');

在目標窗口中,你可以註冊一個事件來接收消息:

1
window.addEventListener('message', function(event) {
2
if (event.origin !== 'https://source-origin.com') return;
3
console.log(event.data); // Outputs: 'Your message here'
4
});

我們的目標僅僅是提供使用者簡便的 Snippet Code,最後採用URL 參數方法。

Result

iframe-snippet.html
1
<!DOCTYPE html>
2
<html lang="en">
3
4
<head>
5
<meta charset="UTF-8">
6
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7
<title>Document</title>
8
</head>
9
10
<body>
11
<iframe
12
src="./target.html?t9=0&poster={POSTER}&autoplay=1&controls=1&preload=1&muted=1&loop=1&t=&src={PATH_TO_M3U8}&vast={PATH_TO_VAST}&clientID={YOUR_CLIENT_ID}"
13
width="500" height="300" frameborder="0"></iframe>
14
</body>
15
1 collapsed line
16
</html>
target.html
1
<!doctype html>
2
<html lang="en">
3
4
<head>
5
<meta charset="UTF-8">
6
<meta name="viewport"
7
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
8
<meta http-equiv="X-UA-Compatible" content="ie=edge">
9
<link href="https://vjs.fusioncdn.com/7.21.4/video-js.min.css" rel="stylesheet">
10
<link href="https://unpkg.com/@videojs/themes@1/dist/fantasy/index.css" rel="stylesheet">
11
<script src="https://vjs.fusioncdn.com/7.21.4/video.min.js"></script>
12
13
<script src="https://imasdk.googleapis.com/js/sdkloader/ima3.js"></script>
14
<script src="https://cdn.jsdelivr.net/npm/videojs-contrib-ads@6.9.0/dist/videojs.ads.min.js"></script>
15
<script src="https://cdn.jsdelivr.net/npm/videojs-ima@2.0.0/dist/videojs.ima.min.js"></script>
138 collapsed lines
16
17
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/videojs-contrib-ads@6.9.0/dist/videojs.ads.css" />
18
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/videojs-ima@2.1.0/dist/videojs.ima.css" />
19
20
<script src="https://vsp.mlytics.co/{YOUR_TOKEN}.js"></script>
21
<script src="https://jsdelivr.fusioncdn.com/npm/@mlytics/p2sp-sdk@latest/bundle/driver.min.js"></script>
22
<script
23
src="https://jsdelivr.fusioncdn.com/npm/@mlytics/p2sp-sdk@latest/bundle/peripheral/player/videojs-hls.min.js"></script>
24
</head>
25
26
<body>
27
<video id="video" class="video-js vjs-theme-fantasy" style="width: 100%; height: 100%; background-color: black;" />
28
29
<script>
30
const loadParameter = () => {
31
const params = new URL(window.location).searchParams;
32
const fetchParameter = (keyName, type, defaultValue) => {
33
let value = params.get(keyName);
34
switch (type) {
35
case 'number':
36
value = Number(value);
37
return typeof value === 'number' && !isNaN(value) ? value : defaultValue;
38
case 'boolean':
39
return [true, 'true', 1, '1'].includes(value) ? true :
40
[false, 'false', 0, '0'].includes(value) ? false :
41
defaultValue;
42
default:
43
return value;
44
}
45
}
46
47
window.parameters = {
48
clientID: fetchParameter('clientID'),
49
src: fetchParameter('src'),
50
vast: fetchParameter('vast'),
51
t: fetchParameter('t', 'number'),
52
poster: fetchParameter('poster'),
53
controls: fetchParameter('controls', 'boolean', false),
54
autoplay: fetchParameter('autoplay', 'boolean', false),
55
loop: fetchParameter('loop', 'boolean', false),
56
preload: fetchParameter('preload', 'boolean', false),
57
muted: fetchParameter('muted', 'boolean', false)
58
}
59
// console.log(`parameters: ${JSON.stringify(parameters)}`);
60
}
61
62
const loadConfig = async () => {
63
await new Promise((resolve, reject) => {
64
try {
65
const element = document.createElement('script');
66
element.setAttribute('src', `https://vsp.mlytics.co/${parameters.clientID}-mlysdk.js`);
67
element.addEventListener('load', () => {
68
resolve();
69
});
70
element.addEventListener('error', () => {
71
reject(new Error('Load mlysdk config failed.'));
72
});
73
document.getElementsByTagName('head')[0].appendChild(element);
74
} catch (error) {
75
reject(error);
76
}
77
});
78
}
79
80
const loadPlayer = async () => {
81
const driver = mlysdk.driver.initialize()
82
83
const src = parameters.src;
84
const video = document.getElementById('video')
85
const adapter = driver.extensions.VideojsHlsPlayerPlugin.create(video, {
86
poster: parameters.poster,
87
controls: parameters.controls,
88
autoplay: parameters.autoplay,
89
loop: parameters.loop,
90
preload: parameters.preload,
91
muted: parameters.muted,
92
sources: [{
93
src,
94
type: 'application/vnd.apple.mpegurl'
95
}],
96
fluid: true
97
})
98
const videojsPlayer = adapter.player
99
100
videojsPlayer.ima({
101
id: 'video',
102
debug: false,
103
showControlsForAds: true,
104
adTagUrl: parameters.vast
105
});
106
videojsPlayer.ima.initializeAdDisplayContainer();
107
108
videojsPlayer.one('adsready', function () {
109
const adsManager = this.ima.getAdsManager();
110
adsManager.addEventListener(
111
google.ima.AdEvent.Type.AD_METADATA,
112
onLoadStart);
113
adsManager.addEventListener(
114
google.ima.AdEvent.Type.STARTED,
115
onAdStarted);
116
adsManager.addEventListener(
117
google.ima.AdEvent.Type.COMPLETE,
118
onAdComplete);
119
});
120
121
function onLoadStart(adEvent) {
122
adapter.protocol.media.mux.emit('adrequest', {
123
ad_tag_url: parameters.vast,
124
});
125
}
126
function onAdStarted(event) {
127
adapter.protocol.media.mux.emit('adbreakstart', {});
128
adapter.protocol.media.mux.emit('adplay', {});
129
adapter.protocol.media.mux.emit('adplaying', {
130
ad_asset_url: event.ad.data.mediaUrl,
131
ad_creative_id: event.ad.data.creativeId,
132
ad_id: event.ad.data.adId,
133
ad_universal_id: event.ad.data.universalAdIdValue
134
});
135
}
136
function onAdComplete(adEvent) {
137
adapter.protocol.media.mux.emit('adended', {});
138
adapter.protocol.media.mux.emit('adbreakend', {});
139
}
140
}
141
142
(async () => {
143
loadParameter();
144
await loadConfig();
145
loadPlayer();
146
147
if (typeof parameters.t === 'number' && parameters.t > 0)
148
videojsPlayer.currentTime(parameters.t);
149
})();
150
</script>
151
</body>
152
153
</html>
本文標題:POC - Solution to integrate iframe with ads featured
文章作者:Vincent Lin
發布時間:2024-03-30