<Sample Html5 Video>
Source: http://html5demos.com/video
현재 | 시작 | 총 재생 시간 |
0 | 0 | 0 |
<참고 자료>
- HTML5 Video: https://www.w3.org/2010/05/video/mediaevents.html
- http://eroi.com/ideas/tracking-video-with-google-analytics-part-3-of-3-html5-edition/
<GA 이벤트 구성>
Event Category |
Event Action |
Event Label |
Event Value | Memo |
HTML5 Video |
Play |
Video Title |
1 | 연속 재생할 때 발생하는 이벤트 제외 |
HTML5 Video |
Pause |
Video Titile |
1 | 연속 재생할 때 발생하는 이벤트 제외 |
HTML5 Video |
Seek |
Video Titile |
1 | 반복 발생하는 이벤트 제외 |
HTML5 Video |
Mute |
Video Titile |
1 | |
HTML5 Video | Unmute | Video Titile | 1 | |
HTML5 Video | Error + Msg | Video Titile | 1 | |
HTML5 Video | PlayTime | Video Titile | 순 재생시간 | |
HTML5 Video | PlayTimeRate | Video Titile | 순 재생시간 비율 |
실제로 동영상을 재생한 시간만 계산하기 위해 동영상의 play, pause 이벤트와 windows.beforeunload 이벤트 이용
<스크립트>
(function(){
// 반복재생(loop)할 경우 이벤트 발생 지점과 동영상 마지막 부분 비교용.
// 차이가 mindiff(초) 보다 작으면 끝까지 재생한 것으로 처리.
// mindiff가 너무 작으면 동영상 끝부분 검출이 안될 수 있음.
var mindiff = 0.5;
// mute와 같은 수준의 볼륨 정의.
var minsound = 0.05;
// 각 동영상에 대한 정보 저장 객체.
var videos_status = {};
var videos = document.getElementsByTagName('video');
function eventHandler(e){
switch(e.type) {
// 동영상 정보 로드 후 정보 저장.
case 'loadeddata':
// 동영상 총 길이(초).
videos_status[e.target.id].duration = e.target.duration;
// 동영상 초기 상태(play, pause, seek).
videos_status[e.target.id].playstatus = (e.target.paused == true) ? 'pause' : 'play';
// 동영상 음소거 여부.
videos_status[e.target.id].muted = e.target.muted;
videos_status[e.target.id].unmuted = !e.target.muted;
break;
case 'timeupdate':
// 동영상의 현재 재생 지점(초) 저장. 재생 중 페이지를 떠날 때 총 재생 시간 계산에 사용.
videos_status[e.target.id].current = e.target.currentTime;
// 반복재생(loop) 상태인지?
if (e.target.loop == true) {
// 동영상 끝에 도달 했는지?
if (videos_status[e.target.id].loopones == true && Math.abs(e.target.duration - e.target.currentTime) < mindiff) {
// 테스트용.
console.log('loop ended');
document.getElementById('eventlog').innerHTML += '>loop ended ';
// 총 재생시간 업데이트. 재생 시작 시간 초기화. 동영상 끝 검출(loopones) 끔.
videos_status[e.target.id].totalplaytime += (e.target.duration - videos_status[e.target.id].startpos);
videos_status[e.target.id].startpos = 0;
videos_status[e.target.id].loopones = false;
}
// 동영상을 처음부터 다시 재생 하는지? 동영상 끝 검출(loopones) 켬.
if (e.target.currentTime < mindiff) videos_status[e.target.id].loopones = true;
}
break;
case 'play':
// seek 할 때 발생하는 play 이벤트 제외 필요. 동영상 재생 중 seek하면 pause -> seeked -> play 순으로 이벤트 발생.
// 현재는 분석 할 때 순수 play 횟수는 play - seek로 계산.
// 동영상 재생 상태를 play로 변경.
videos_status[e.target.id].playstatus = 'play';
// 재생 시작 시점을 현재 시점으로 설정.
videos_status[e.target.id].startpos = e.target.currentTime;
// 반복재생(loop) 상태에서 발생하는 play 이벤트 제외함.
// 이 때문에 동영상 마지막 부분 직전에서 재생을 클릭해도 GA 이벤트 발생하지 않음.
if ((e.target.loop == false) || (Math.abs(e.target.duration - e.target.currentTime) > mindiff)) {
dataLayer.push({
'event': 'Html5VideoEvent',
'eventCategory': 'HTML5 Video',
'eventAction': 'Play',
'eventLabel': videos_status[e.target.id].videotitle,
'eventValue' : 1
});
}
break;
case 'pause':
// seek 할 때 발생하는 pause 이벤트 제외 필요.
// 현재는 분석 할 때 순수 pause 횟수는 pause - seek로 계산.
// 동영상 재생 상태를 pause로 변경.
videos_status[e.target.id].playstatus = 'pause';
// 동영상 재생시점과 현재 시점 간 오류가 있는지?
if (videos_status[e.target.id].startpos > e.target.currentTime) {
console.log('error : startpos = ' + videos_status[e.target.id].startpos + ', currentTime = ' + e.target.currentTime);
}
// 총 재생시간 업데이트.
videos_status[e.target.id].totalplaytime += (e.target.currentTime - videos_status[e.target.id].startpos);
if ((e.target.loop == true) && (Math.abs(e.target.duration - e.target.currentTime) < mindiff)) {
// 반복재생(loop) 상태에서 발생하는 pause 이벤트 제외함.
// 이 때문에 동영상 마지막 부분 직전에서 멈춤을 클릭해도 GA 이벤트 발생하지 않음.
} else {
// 반복재생(loop) 상태가 아니거나, 현재 재생시점이 mindiff보다 큼 경우만 pause GA 이벤트 발생.
// 테스트용.
dataLayer.push({
'event': 'Html5VideoEvent',
'eventCategory': 'HTML5 Video',
'eventAction': 'Pause',
'eventLabel': videos_status[e.target.id].videotitle,
'eventValue': 1
});
}
break;
case 'seeked':
// 연속해서 발생한 seek 이벤트 제외. 반복재생(loop) 상태에서 동영상 처음으로 돌아갈 때 발생하는 seeked 이벤트 제외함.
// 중지(pause) 상태에서 발생하는 seek도 한번만 발생됨.
if ((videos_status[e.target.id].playstatus != 'seek') && (videos_status[e.target.id].loopones == true && Math.abs(e.target.duration - e.target.currentTime) > mindiff)) {
dataLayer.push({
'event': 'Html5VideoEvent',
'eventCategory': 'HTML5 Video',
'eventAction': 'Seek',
'eventLabel': videos_status[e.target.id].videotitle,
'eventValue' : 1
});
// 동영상 재생 상태를 seek로 변경.
videos_status[e.target.id].playstatus = 'seek';
}
break;
case 'volumechange':
// 음소거 또는 최소 볼륨(minsound) 미만으로 변경할 때 한 번만 GA 이벤트 발생. (unmute에서 mute로 변경 시 1회 발생)
if ((videos_status[e.target.id].muted == false) && (e.target.muted == true || e.target.volume < minsound)) {
videos_status[e.target.id].muted = true;
videos_status[e.target.id].unmuted = false;
dataLayer.push({
'event': 'Html5VideoEvent',
'eventCategory': 'HTML5 Video',
'eventAction': 'Mute',
'eventLabel': videos_status[e.target.id].videotitle,
'eventValue' : 1
});
}
// 음소거 해제 또는 최소 볼륨(minsound) 이상으로 변경할 때 한 번만 GA 이벤트 발생. (mute에서 unmute로 변경 시 1회 발생)
if ((videos_status[e.target.id].unmuted == false) && (e.target.muted == false) && (e.target.volume >= minsound)) {
videos_status[e.target.id].muted = false;
videos_status[e.target.id].unmuted = true;
dataLayer.push({
'event': 'Html5VideoEvent',
'eventCategory': 'HTML5 Video',
'eventAction': 'Unmute',
'eventLabel': videos_status[e.target.id].videotitle,
'eventValue' : 1
});
}
break;
case 'error':
dataLayer.push({
'event': 'Html5VideoEvent',
'eventCategory': 'HTML5 Video',
'eventAction': 'Error - ' + e.target.error,
'eventLabel': videos_status[e.target.id].videotitle,
'eventValue' : 1
});
break;
default:
break;
}
}
function onbeforeunloadHandler(e) {
for (var v in videos_status) {
// 페이지를 떠나려고 할 때 동영상이 재생 중이라면 총 재생시간 업데이트.
if (videos_status[v].playstatus == 'play') {
videos_status[v].totalplaytime += (videos_status[v].current - videos_status[v].startpos);
}
// 재생한 동영상의 총 재생시간 GA 이벤트 발생.
if (videos_status[v].totalplaytime > 0) {
// 총 재생시간
console.log('onbeforeunloadHandler');
document.getElementById('eventlog').innerHTML += '> onbeforeunloadHandler ';
dataLayer.push({
'event': 'Html5VideoEvent',
'eventCategory': 'HTML5 Video',
'eventAction': 'PlayTime',
'eventLabel': videos_status[v].videotitle,
'eventValue' : Math.round(videos_status[v].totalplaytime)
});
// 총 재생시간 비율. 100%가 동영상의 전체 부분을 봤다는 뜻은 아님. 10초 길이 동영상의 0~1초 부분을 10번 봐도 100%가 됨.
dataLayer.push({
'event': 'Html5VideoEvent',
'eventCategory': 'HTML5 Video',
'eventAction': 'PlayTimeRate',
'eventLabel': videos_status[v].videotitle,
'eventValue' : Math.round(100 * videos_status[v].totalplaytime / videos_status[v].duration)
});
}
}
}
for (var i = 0; i < videos.length; i++) {
var videoTagId;
var videoTitle;
// 동영상의 ID 설정.
if (!videos[i].getAttribute('id')) {
videoTagId = 'html5_video_' + Math.random().toString(36).slice(2);
videos[i].setAttribute('id', videoTagId);
}
else {
videoTagId = videos[i].getAttribute('id');
}
// 동영상의 제목 설정.
if (!videos[i].getAttribute('data-title')) {
videoTitle = videos[i].currentSrc;
} else {
videoTitle = videos[i].getAttribute('data-title');
}
// 동영상 정보 초기화.
videos_status[videoTagId] = {};
videos_status[videoTagId].startpos = 0;
videos_status[videoTagId].current = 0;
videos_status[videoTagId].playpos = 0;
videos_status[videoTagId].totalplaytime = 0;
videos_status[videoTagId].loopones = true;
videos_status[videoTagId].videotitle = videoTitle;
// 동영상의 이벤트 핸들러 설정.
videos[i].addEventListener("loadeddata", eventHandler, false);
videos[i].addEventListener("play", eventHandler, false);
videos[i].addEventListener("pause", eventHandler, false);
videos[i].addEventListener("seeked", eventHandler, false);
videos[i].addEventListener("timeupdate", eventHandler, false);
videos[i].addEventListener("volumechange", eventHandler, false);
videos[i].addEventListener("error", eventHandler, false);
}
// 페이지의 이벤트 핸들러 설정.beforeunload
window.addEventListener("beforeunload", onbeforeunloadHandler, false);
})();
'Goolge Analytics' 카테고리의 다른 글
Youtube 동영상 GTM Tracking Test (0) | 2016.08.23 |
---|---|
구글 애널리틱스 문제 풀이#7 (0) | 2016.08.23 |
구글 애널리틱스 보고서 내려받기(엑셀) (0) | 2016.08.18 |
구글 애널리틱스 문제 풀이#6 (0) | 2016.08.05 |
맞춤 캠페인 URL 관리(Custom Campaign URL Builder) (0) | 2016.07.19 |