// ==UserScript==
// @namespace https://tampermonkey.myso.kr/
// @name 네이버 블로그 게시물 유입 통계 어드밴스드
// @description 네이버 블로그 게시물 최근 유입 통계를 확인합니다.
// @copyright 2021, myso (https://tampermonkey.myso.kr)
// @license Apache-2.0
// @version 1.0.5
// @author Won Choi
// @connect naver.com
// @match *://blog.naver.com/PostView*
// @match *://blog.naver.com/PostList*
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@1.0.25/assets/vendor/gm-app.js
// @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@1.0.25/assets/vendor/gm-add-style.js
// @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@1.0.25/assets/vendor/gm-add-script.js
// @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@1.0.25/assets/vendor/gm-xmlhttp-request-async.js
// @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@1.0.25/assets/donation.js
// @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@1.0.25/assets/lib/naver-blog.js
// @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@1.0.25/assets/lib/naver-blog-content.js
// @require https://cdnjs.cloudflare.com/ajax/libs/uuid/8.3.2/uuidv4.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.7.2/bluebird.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.7/handlebars.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.33/moment-timezone.min.js
// @downloadURL https://update.greasyfork.icu/scripts/428764/%EB%84%A4%EC%9D%B4%EB%B2%84%20%EB%B8%94%EB%A1%9C%EA%B7%B8%20%EA%B2%8C%EC%8B%9C%EB%AC%BC%20%EC%9C%A0%EC%9E%85%20%ED%86%B5%EA%B3%84%20%EC%96%B4%EB%93%9C%EB%B0%B4%EC%8A%A4%EB%93%9C.user.js
// @updateURL https://update.greasyfork.icu/scripts/428764/%EB%84%A4%EC%9D%B4%EB%B2%84%20%EB%B8%94%EB%A1%9C%EA%B7%B8%20%EA%B2%8C%EC%8B%9C%EB%AC%BC%20%EC%9C%A0%EC%9E%85%20%ED%86%B5%EA%B3%84%20%EC%96%B4%EB%93%9C%EB%B0%B4%EC%8A%A4%EB%93%9C.meta.js
// ==/UserScript==
// ==OpenUserJS==
// @author myso
// ==/OpenUserJS==
GM_App(async function main() {
moment.tz.setDefault("Asia/Seoul");
GM_donation('#viewTypeSelector, #postListBody, #wrap_blog_rabbit, #writeTopArea, #editor_frame', 0);
GM_addStyle(`a._readReferrer .ico_spd { display: block; position: absolute; right: 13px; top: 13px; width: 20px; height: 20px; text-align: center; line-height: 20px; font-size:11px; font-weight: bold; }`);
async function popup(data) {
const tmpl = Handlebars.compile(`
콘텐츠 유입 분석 결과
콘텐츠 유입 분석 결과
{{tail.date}} ~ {{head.date}}
{{#each items}}
-
{{date}}
{{#each stats}}
-
{{referrerDomain}}
총 {{cv}}건의 유입
{{#each detail.refererDetail}}
-
{{#if searchQuery}}[{{searchQuery}}] {{/if}}{{referrerUrl}}
{{cv}}건의 유입
{{/each}}
{{/each}}
{{/each}}
`);
const html = tmpl(data);
const blob = new Blob([html], {type : 'text/html'});
return window.open(URL.createObjectURL(blob), '_readReferrer', 'width=600, height=960');
}
async function start(event, contentId, range) {
const dates = _.range(range).map(o=>moment().subtract(o, 'days').toISOString(true));
const items = await Promise.map(dates, async (date) => {
const total = await NB_blogPostStat(contentId, 'referer/total', date, 'DATE');
const stats = await Promise.map(total.refererTotal, async (item) => {
const detail = await NB_blogPostStat(contentId, 'referer/total/detail', date, 'DATE', { searchEngine: item.referrerSearchEngine, refererDomain: item.referrerDomain })
if(detail && detail.refererDetail){
detail.refererDetail = detail.refererDetail.map((item)=>{
const uri = ((url)=>{ try { return new URL(url); } catch(e) {} })(item.referrerUrl);
const qry = item.searchQuery = ['query', 'q', 'keyword', 'searchKeyword'].reduce((r, k)=>r||(uri && uri.searchParams.get('query')), '') || item.searchQuery || '';
return item;
});
}
return Object.assign({}, item, { detail });
});
return Object.assign({ date: moment(date).format('YYYY-MM-DD'), stats });
});
const head = _.head(items);
const tail = _.last(items);
popup({ head, tail, items });
}
async function handler(event) {
const wrappers = Array.from(document.querySelectorAll('[data-post-editor-version]'));
wrappers.map((wrapper) => {
const menu = wrapper.querySelector('.lyr_overflow_menu'); if(!menu) return;
const stat = wrapper.querySelector('.btn_stat'); if(!stat) return;
const param = /_param\(([^\(\)]+)\)/.exec(stat.className), value = param && param[1]; if(!value) return;
const contentId = value.replace(/^(.*?)([\d]{12})(.*?)$/, '$2'); if(!contentId) return;
const menu_append = (title, range = 7) => {
const item = menu.querySelector(`a._readReferrer._readReferrer${range}`) || document.createElement('a'); if(item.className) return;
item.classList.add('_readReferrer', `_readReferrer${range}`); item.href = '#'; menu.append(item); item.innerHTML = `${title} ${range}일`;
item.onclick = async function(event) { event.preventDefault(); await start(event, contentId, range); }
}
menu_append('유입통계', 7);
menu_append('유입통계', 30);
});
}
window.addEventListener('keyup', handler, false);
window.addEventListener('keydown', handler, false);
window.addEventListener('keypress', handler, false);
window.addEventListener('click', handler, false);
handler();
});