이 문서는 rake-javascript v3.x.x 의 사용법에 대해서 설명합니다.
구 버전의 사용은 다음을 참고하세요.
Basics
아래 내용을 꼭 읽기를 권장합니다.
- rake-javascript(이하 RC-JS)는 Google Analytics(이하 GA)와 동일하게 비동기로 로딩되어 Page View 또는 Custom Format 로그를 전송합니다.
- (중요) 사용자 환경 구분을 위해
_$RAKE_ENV 를 입력받습니다.
| 환경 |
_$RAKE_ENV 값 |
| 상용서버로 전송 |
LIVE |
| 개발서버로 전송 |
DEV |
WebView라면 Native와의 통신을 이용해 device_id 값을 가져오거나, 데이터를 Native로 넘겨 Android, iPhone 용 Rake를 이용해 전송할 수 있습니다.
다른 방법으로는 직접 device_id 값을 shuttle 에 입력할 수 있습니다. 다만 이 경우 포맷은 String 이어야 올바르게 암호화가 됩니다. 예를 들어 {"device_id_from_web": "48FFAA"} 는 암호화를 지원하지 않습니다.
(escaping 된 값의 경우 가능하나, 권장하지 않습니다.)
Mobile Web이나 Web이라면 uuid 값을 device_id 값 대용으로 사용할 수 있습니다.(Web view에서도 생성 및 전송 가능).
단 uuid 값을 shuttle의 header에 포함시켜야 하고 포맷은 String이어야 합니다.
- XHR을 지원하지 않는 브라우저를 위해서 XDR을 이용해 지원합니다. 다만 XDR Limitation 때문에 HTTPS(Rake Server)로 전송하려면, Client 페이지 또한 HTTPS 이어야 합니다.
- 비동기로 로딩되는 스크립트의 사이즈는 브라우저 종류에 따라 다르며 이는 브라우저 호환성을 맞추기 위한 Polyfill 때문입니다.
| 브라우저 종류 |
스크립트 사이즈 |
스크립트 이름 |
| Modern |
27 KB |
rake.bundle.js |
| IE 9, 10 |
25 KB |
rake.bundle-ie.js |
| IE 8 |
47 KB |
rake.bundle-ie8.js |
Usage
1. Sentinel Shuttle
- Rake 는 Sentinel-Shuttle 과 같이 사용됩니다. Shuttle 은 로그 디자이너가 정의한 포맷에 맞게 로그를 남길 수 있도록 도와주는 POJO (= DTO, VO) 입니다. 따라서 Shuttle 없이는 Rake 를 사용할 수 없습니다.
- Shuttle을 Sentinel에서 다운받아
<script> 태그를 이용해 추가합니다. 이 예제에서는 Shuttle 클래스의 이름을 MyAppShuttle 이라 가정하겠습니다.
2. Snippet
- Snippet 코드를 통해서 비동기로 로딩되는 RC-JS의 동작을 제어할 수 있습니다.
2-1. Snippet 사용방법
- 아래 Snippet 코드를 Copy하여 애플리케이션 스크립트 상단에 넣어주세요.
<!-- start RC-JS --><script type="text/javascript">
// RC-JS를 비동기로 로딩하는 Snippet 입니다.
(function () {function a(r,e,$){return e in r?Object.defineProperty(r,e,{"value":$,"enumerable":!0,"configurable":!0,"writable":!0}):r[e]=$,r}var j=function(e){return e.userAgent.toLowerCase()};var l=function(e){var r=e.userAgent;return"Netscape"===e.appName&&r.indexOf("trident")>-1||r.indexOf("msie")>-1||r.indexOf("edge")>-1};var k=function(e){return e.indexOf("msie")<0?0:parseInt(e.split("msie")[1],10)};var b="RAKE";var f="_$OPTIONS";var g="_$loaded";var i="_$cb";var c="_$RAKE_ENV";var h="_$SV";var d="_$RAKE_MODE";var m=function(e,t){var r=!(arguments.length>2&&arguments[2]!==undefined)||arguments[2],$={};for(var o in e)e.hasOwnProperty(o)&&($[o]=e[o]);for(var n in t)t.hasOwnProperty(n)&&(r?$[n]=t[n]:e[n]=t[n]);return r?$:e};var n="1.0",o="rake.bundle.js",p="rake.bundle-ie8.js",q="rake.bundle-ie.js",e=function(r,e){return{"init":function($){e[h]||(function(){var r,$=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};m(e,(a(r={},g,!1),a(r,f,$[f]||{}),a(r,d,$[d]||[]),a(r,c,$[c]||"LIVE"),a(r,h,n),a(r,i,function(){}),r),!1)}($),function(){if(!r.getElementById(b)){var $=r.createElement("script"),t=r.getElementsByTagName("script")[0];$.id=b,$.type="text/javascript",$.async=!0,$.src=function(r){var e="DEV"===r?"https://pg.rake.skplanet.com:8443/log/static/js/rake/new/current":"LIVE"===r?"https://rake.skplanet.com:8443/log/static/js/rake/new/current":"",$=window.navigator,t=$.appName,c=j($),n="".concat(e,"/").concat(o);if(l({"userAgent":c,"appName":t})){var i=k(c);8===i?n="".concat(e,"/").concat(p):i>8&&i<11&&(n="".concat(e,"/").concat(q))}return n}(e[c]),t.parentNode.insertBefore($,t)}}(),function(){if(!e[g])for(var r=["track","flush","create","remove","collect","autoTrack","setServerURL","setServerPort","excludeAutoProperties"],$=function($,t){var c=r[$];e[c]=function(){var r=Array.prototype.slice.call(arguments,0),$=[c];$=$.concat(r),e.push($)}},t=0,c=r.length;t<c;t++)$(t,c)}(),window[b]=e)}}}(document,window[b]||[]);window.snippet=e;})();
// Snippet 옵션 설정
snippet.init();
</script><!-- end RC-JS -->
2-2. Snippet 옵션
| 키 |
설명 |
필수 |
타입 |
| _$RAKE_ENV |
사용자 환경 구분 (상용(기본):LIVE, 개발:DEV) |
X |
String |
| _$RAKE_MODE |
RC-JS + α의 기능 (현재는 DMP만 지원) |
X |
Array |
| _$OPTIONS |
RC-JS 동작에 필요한 값 |
X |
Object |
| 키 |
설명 |
필수 |
타입 |
| isBeacon |
브라우저의 Beacon 기능 사용 유무 |
X |
Boolean |
| isCookieSync |
DMP의 PIXEL(Cookie Sync) API 연동 유무 |
X |
Boolean |
| nid |
DMP의 PIXEL API 연동 시 사용하는 제휴사 식별자 |
X |
String |
| uid |
DMP의 PIXEL API 연동 시 사용하는 제휴사 사용자 식별자 |
X |
String |
// Snippet 옵션 설정
snippet.init({
_$RAKE_ENV: 'DEV',
_$RAKE_MODE: ['DMP'],
_$OPTIONS: {
isBeacon: true,
isCookieSync: true,
nid: '제휴사 식별자',
uid: '제휴사 사용자 식별자'
}
});
2-3. Snippet 옵션을 통한 RC-JS 기능
1) DMP 기능
- 자체적으로 DMP의 도메인 비실명 Cookie UID를 운영하고 PIXEL(Cookie Sync)를 사용하는 경우
_$OPTIONS 필드에 isCookieSync, nid, uid 를 설정합니다.
2) Beacon 기능
Beacon 은 페이지 전환 시 전송 요청이 취소(XDR 혹은 XHR)되는 브라우저의 특징을 보완하여 Beacon 으로 로그 전송을 보장합니다. (RC-JS 기본 전송모드: XDR 혹은 XHR)
_$OPTIONS 필드에 isBeacon 을 true로 설정하면, Beacon 모드로 전송합니다. 다만 true 값이지만 Beacon 을 지원하지 않는 브라우저(IE)에서는 XDR 혹은 XHR로 전송이 됩니다.
Beacon 전송 시 successCallback, failureCallback, timeoutAsMillis 비활성 됩니다.
3. Rake API
3-1 create()
- Rake 인스턴스를 생성한다.
- DMP 기능
DMP 기능을 사용하기 위해서 snippet.init() 에 _$RAKE_MODE: ['DMP'] 를 추가합니다.
DMP 모듈을 사용 시 PIXEL API를 호출하여 dmp_uid 를 발급 받고, 이후 GETUID API를 통해서 DMP 에서 발급된 dmp_uid 를 localStorage에 저장합니다.
- localStorage에 저장된
dmp_uid 를 Payload의 header에 저장하여 보내기 위해서 Rake Instance 생성 시 isDMP 을 넣어야 합니다. (다중 Instance 지원 때문)
- UUID 기능
UUID 기능을 사용하기 위해서 RAKE Instance 생성 시 Parameters에 uuid:true를 입력합니다.
UUID 기능 사용 시, localStorage에 RAKE:uuid를 key값으로 identifier를 생성,저장하고 전송합니다.
- localStorage에 저장된
RAKE:uuid를 Payload의 header에 저장하여 보내기 위해서 Rake Instnace 생성 시 uuid를 true로 설정해야 합니다.
- Parameters
| 키 |
설명 |
필수 |
타입 |
| instanceAlias |
Instance 별칭 (다중 Instance 사용 시 필수이며, 설정 시 다른 API(예: track 등)에서도 설정해야함) |
X |
String |
| token |
Sentinel에서 발급받은 Token 값 |
O |
String |
| isDMP |
DMP 기능 활성 유무 (기본: false) |
X |
Boolean |
| uuid |
UUID 기능 활성 유무 (기본: false) |
X |
Boolean |
| filters |
URL이 모두 매칭될 경우에만 전송 |
X |
Array |
| converters |
URL Query 혹은 Cookie 값을 Payload로 설정해서 전송 |
X |
Array |
| 키 |
설명 |
필수 |
타입 |
| type |
현재는 URL_INCLUDES_ALL(URL 모두 매칭)만 지원 |
O |
String |
| patterns |
URL에 매칭할 키워드 (없거나 빈 배열일 경우 모두 전송) |
X |
Array |
| 키 |
설명 |
필수 |
타입 |
| type |
URL_QUERY_TO_PAYLOAD, COOKIE_TO_PAYLOAD |
O |
String |
| from |
URL Query 혹은 Cookie에서 사용할 Key 값 |
O |
String |
| to |
Payload에 설정할 Key 값 |
O |
String |
% Payload 설정 시 body에 설정하고 싶으면, _$body.TO값 설정 (예: body의 속성으로 user_session 을 설정하고 싶으면 _$body.user_session)
// Rake Instance 생성
RAKE.create({
instanceAlias: 'Instance 별칭',
token: 'Sentinel에서 발급받은 Token 값',
isDMP: true,
uuid: true,
filters: [
{ type: 'URL_INCLUDES_ALL', patterns: ['localhost', 'index.html'] }
],
converters: [
// URL에서 QueryString 중 userSession 값을 추출하여 body의 user_session 필드에 삽입
{ type: 'URL_QUERY_TO_PAYLOAD', from: 'userSession', to: '_$body.user_session' },
// URL에서 QueryString 중 userId 값을 추출하여 header의 user_id 필드에 삽입
{ type: 'URL_QUERY_TO_PAYLOAD', from: 'userId', to: 'user_id' },
// 브라우저 Cookie에서 cookieSession 값을 추출하여 header의 cookie_session 필드에 삽입
{ type: 'COOKIE_TO_PAYLOAD', from: 'cookieSession', to: 'cookie_session' }
]
});
3-2 autoTrack()
- create() + track() 기능
- Parameters
| 키 |
설명 |
필수 |
타입 |
| instanceAlias |
Instance 별칭 (다중 Instance 사용 시 설정) |
X |
String |
| token |
Sentinel에서 발급받은 Token 값 |
O |
String |
| shuttle |
Shuttle 생성자 명 (Payload 생성용) |
O |
String |
| isDMP |
DMP 기능 활성 유무 (기본: false) |
X |
Boolean |
| uuid |
UUID 기능 활성 유무 (기본: false) |
X |
Boolean |
| filters |
URL이 모두 매칭될 경우에만 전송 (상세 코드는 3-1 create() 참조) |
X |
Array |
| converters |
URL Query 혹은 Cookie 값을 Payload로 설정해서 전송 (상세 코드는 3-1 create() 참조) |
X |
Array |
| timeoutAsMillis |
전송 Timeout 밀리초 (기본: 15000) |
X |
Number |
| successCallback |
전송 성공 시 Callback |
X |
Function |
| failureCallback |
전송 실패 시 Callback |
X |
Function |
// Rake Instance 자동 생성 및 전송
RAKE.autoTrack({
instanceAlias: 'Instance 별칭',
token: 'Sentinel에서 발급받은 Token 값',
shuttle: MyAppShuttle, // Shuttle 생성자 명
isDMP: true,
uuid: true,
filters: [
{ type: 'URL_INCLUDES_ALL', patterns: ['localhost', 'index.html'] }
],
converters: [
// URL에서 QueryString 중 userSession 값을 추출하여 body의 user_session 필드에 삽입
{ type: 'URL_QUERY_TO_PAYLOAD', from: 'userSession', to: '_$body.user_session' },
// URL에서 QueryString 중 userId 값을 추출하여 header의 user_id 필드에 삽입
{ type: 'URL_QUERY_TO_PAYLOAD', from: 'userId', to: 'user_id' },
// 브라우저 Cookie에서 cookieSession 값을 추출하여 header의 cookie_session 필드에 삽입
{ type: 'COOKIE_TO_PAYLOAD', from: 'cookieSession', to: 'cookie_session' }
],
timeoutAsMillis: 1000,
successCallback: function() { console.log('SUCCESS CALLBACK') },
failureCallback: function() { console.log('FAILURE CALLBACK') }
});
3-3 track()
- Payload를 메모리(localStorage)에 적재하고 바로 전송합니다. (1건씩 처리용, collect() + flush() 기능)
- Parameters
| 키 |
설명 |
필수 |
타입 |
| instanceAlias |
Instance 별칭 (다중 Instance 사용 시 필수이며, 설정 시 다른 API(예: track 등)에서도 설정해야함) |
X |
String |
| payload |
Shuttle을 이용한 Payload 값 |
O |
Object |
| timeoutAsMillis |
전송 Timeout 밀리초 (기본: 15000) |
X |
Number |
| successCallback |
전송 성공 시 Callback |
X |
Function |
| failureCallback |
전송 실패 시 Callback |
X |
Function |
// 전송할 Payload 생성
const shuttle = new MyAppShuttle();
shuttle.setAction_id('view');
shuttle.setPage_id('49E-FF01');
const myPayload = shuttle.getImmutableJSONObject();
// Payload 전송
RAKE.track({
instanceAlias: 'Instance 별칭', // create()에서 설정한 instanceAlias
payload: myPayload,
timeoutAsMillis: 1000,
successCallback: function() { console.log('SUCCESS CALLBACK') },
failureCallback: function() { console.log('FAILURE CALLBACK') }
});
3-4 collect()
- Payload를 리스트 형태로 메모리(localStorage)에 적재합니다. (전송 실패 및 유실 방지용)
- DMP 기능
- create() 생성 시
isDMP: true 이면, localStorage에 저장된 dmp_uid 를 header의 dmpc 에 설정
- UUID 기능
- create() 생성 시
uuid: true 이면, localStorage에 저장된 RAKE:uuid 를 header의 uuid 에 설정
- Parameters
| 키 |
설명 |
필수 |
타입 |
| instanceAlias |
Instance 별칭 (다중 Instance 사용 시 필수이며, 설정 시 다른 API(예: track 등)에서도 설정해야함) |
X |
String |
| payload |
Shuttle을 이용한 Payload 값 |
O |
Object |
// 전송할 Payload 생성 및 적재 01
const shuttle = new MyAppShuttle();
shuttle.setAction_id('view');
shuttle.setPage_id('49E-FF01');
RAKE.collect({
instanceAlias: 'Instance 별칭', // create()에서 설정한 instanceAlias
payload: shuttle.getImmutableJSONObject()
});
// 전송할 Payload 생성 및 적재 02
shuttle.setAction_id('click');
shuttle.setPage_id('49E-FF02');
RAKE.collect({
instanceAlias: 'Instance 별칭', // create()에서 설정한 instanceAlias
payload: shuttle.getImmutableJSONObject()
});
3-5 flush()
- 리스트 형태로 메모리(localStorage)에 적재된 Payload를 서버에 전송합니다.
- 전송 실패시 메모리에 재적재합니다. (메모리 적재 사이즈: 100개)
- Parameters
| 키 |
설명 |
필수 |
타입 |
| instanceAlias |
Instance 별칭 (다중 Instance 사용 시 필수이며, 설정 시 다른 API(예: track 등)에서도 설정해야함) |
X |
String |
| timeoutAsMillis |
전송 Timeout 밀리초 (기본: 15000) |
X |
Number |
| successCallback |
전송 성공 시 Callback |
X |
Function |
| failureCallback |
전송 실패 시 Callback |
X |
Function |
// 전송
RAKE.flush({
instanceAlias: 'Instance 별칭', // create()에서 설정한 instanceAlias
timeoutAsMillis: 1000,
successCallback: function() { console.log('SUCCESS CALLBACK') },
failureCallback: function() { console.log('FAILURE CALLBACK') }
});
예제 코드
<html lang="en">
<body>
<!-- start RC-JS --><script type="text/javascript">
// RC-JS를 비동기로 로딩하는 Snippet 입니다.
(function () {function a(r,e,$){return e in r?Object.defineProperty(r,e,{"value":$,"enumerable":!0,"configurable":!0,"writable":!0}):r[e]=$,r}var j=function(e){return e.userAgent.toLowerCase()};var l=function(e){var r=e.userAgent;return"Netscape"===e.appName&&r.indexOf("trident")>-1||r.indexOf("msie")>-1||r.indexOf("edge")>-1};var k=function(e){return e.indexOf("msie")<0?0:parseInt(e.split("msie")[1],10)};var b="RAKE";var f="_$OPTIONS";var g="_$loaded";var i="_$cb";var c="_$RAKE_ENV";var h="_$SV";var d="_$RAKE_MODE";var m=function(e,t){var r=!(arguments.length>2&&arguments[2]!==undefined)||arguments[2],$={};for(var o in e)e.hasOwnProperty(o)&&($[o]=e[o]);for(var n in t)t.hasOwnProperty(n)&&(r?$[n]=t[n]:e[n]=t[n]);return r?$:e};var n="1.0",o="rake.bundle.js",p="rake.bundle-ie8.js",q="rake.bundle-ie.js",e=function(r,e){return{"init":function($){e[h]||(function(){var r,$=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};m(e,(a(r={},g,!1),a(r,f,$[f]||{}),a(r,d,$[d]||[]),a(r,c,$[c]||"LIVE"),a(r,h,n),a(r,i,function(){}),r),!1)}($),function(){if(!r.getElementById(b)){var $=r.createElement("script"),t=r.getElementsByTagName("script")[0];$.id=b,$.type="text/javascript",$.async=!0,$.src=function(r){var e="DEV"===r?"https://pg.rake.skplanet.com:8443/log/static/js/rake/new/current":"LIVE"===r?"https://rake.skplanet.com:8443/log/static/js/rake/new/current":"",$=window.navigator,t=$.appName,c=j($),n="".concat(e,"/").concat(o);if(l({"userAgent":c,"appName":t})){var i=k(c);8===i?n="".concat(e,"/").concat(p):i>8&&i<11&&(n="".concat(e,"/").concat(q))}return n}(e[c]),t.parentNode.insertBefore($,t)}}(),function(){if(!e[g])for(var r=["track","flush","create","remove","collect","autoTrack","setServerURL","setServerPort","excludeAutoProperties"],$=function($,t){var c=r[$];e[c]=function(){var r=Array.prototype.slice.call(arguments,0),$=[c];$=$.concat(r),e.push($)}},t=0,c=r.length;t<c;t++)$(t,c)}(),window[b]=e)}}}(document,window[b]||[]);window.snippet=e;})();
// Snippet 옵션 설정
snippet.init({
_$RAKE_ENV: 'DEV',
_$RAKE_MODE: ['DMP'],
_$OPTIONS: {
isBeacon: true,
isCookieSync: true,
nid: '제휴사 식별자',
uid: '제휴사 사용자 식별자'
}
});
</script><!-- end RC-JS -->
<!-- Shuttle 스크립트 로딩 -->
<script src="./shuttle/MyAppShuttle.js"></script>
<script type="text/javascript">
const test = () => {
// Rake Instance 생성
RAKE.create({
instanceAlias: 'Instance 별칭',
token: 'Sentinel에서 발급받은 Token 값',
isDMP: true,
uuid: true,
filters: [
{ type: 'URL_INCLUDES_ALL', patterns: ['localhost', 'index.html'] }
],
converters: [
// URL에서 QueryString 중 userSession 값을 추출하여 body의 user_session 필드에 삽입
{ type: 'URL_QUERY_TO_PAYLOAD', from: 'userSession', to: '_$body.user_session' },
// URL에서 QueryString 중 userId 값을 추출하여 header의 user_id 필드에 삽입
{ type: 'URL_QUERY_TO_PAYLOAD', from: 'userId', to: 'user_id' },
// 브라우저 Cookie에서 cookieSession 값을 추출하여 header의 cookie_session 필드에 삽입
{ type: 'COOKIE_TO_PAYLOAD', from: 'cookieSession', to: 'cookie_session' }
]
});
/*
* track() 테스트
*/
// 전송할 Payload 생성
const shuttle = new MyAppShuttle();
shuttle.setAction_id('view');
shuttle.setPage_id('49E-FF01');
const myPayload = shuttle.getImmutableJSONObject();
// Payload 전송
RAKE.track({
instanceAlias: 'Instance 별칭', // create()에서 설정한 instanceAlias
payload: myPayload,
timeoutAsMillis: 1000,
successCallback: function() { console.log('SUCCESS CALLBACK for Track') },
failureCallback: function() { console.log('FAILURE CALLBACK for Track') }
});
/*
* collect() + flush() 테스트
*/
// 전송할 Payload 생성 및 적재 01
// const shuttle = new MyAppShuttle(); // 앞에서 선언해서 주석 처리
shuttle.setAction_id('view');
shuttle.setPage_id('49E-FF01');
RAKE.collect({
instanceAlias: 'Instance 별칭', // create()에서 설정한 instanceAlias
payload: shuttle.getImmutableJSONObject()
});
// 전송할 Payload 생성 및 적재 02
shuttle.setAction_id('click');
shuttle.setPage_id('49E-FF02');
RAKE.collect({
instanceAlias: 'Instance 별칭', // create()에서 설정한 instanceAlias
payload: shuttle.getImmutableJSONObject()
});
// 전송
RAKE.flush({
instanceAlias: 'Instance 별칭', // create()에서 설정한 instanceAlias
timeoutAsMillis: 1000,
successCallback: function() { console.log('SUCCESS CALLBACK for Collect + Flush') },
failureCallback: function() { console.log('FAILURE CALLBACK for Collect + Flush') }
});
};
setTimeout(test, 1000);
const test_autoTrack = () => {
// Rake Instance 자동 생성 및 전송
RAKE.autoTrack({
instanceAlias: 'Instance 별칭',
token: 'Sentinel에서 발급받은 Token 값',
shuttle: MyAppShuttle, // Shuttle 생성자 명
isDMP: true,
uuid: true,
filters: [
{ type: 'URL_INCLUDES_ALL', patterns: ['localhost', 'index.html'] }
],
converters: [
// URL에서 QueryString 중 userSession 값을 추출하여 body의 user_session 필드에 삽입
{ type: 'URL_QUERY_TO_PAYLOAD', from: 'userSession', to: '_$body.user_session' },
// URL에서 QueryString 중 userId 값을 추출하여 header의 user_id 필드에 삽입
{ type: 'URL_QUERY_TO_PAYLOAD', from: 'userId', to: 'user_id' },
// 브라우저 Cookie에서 cookieSession 값을 추출하여 header의 cookie_session 필드에 삽입
{ type: 'COOKIE_TO_PAYLOAD', from: 'cookieSession', to: 'cookie_session' }
],
timeoutAsMillis: 1000,
successCallback: function() { console.log('SUCCESS CALLBACK for AutoTrack') },
failureCallback: function() { console.log('FAILURE CALLBACK for AutoTrack') }
});
};
// setTimeout(test_autoTrack, 1000);
</script>
<h1>RakeApp-Example</h1>
</body>
</html>