NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name YouTube Enhancer (Secret Stats) // @description Integrating "Secret Stats" and "Stream Stats" buttons into the channel page, directing users to detailed analytics pages for insights into the channel. // @icon https://raw.githubusercontent.com/exyezed/youtube-enhancer/refs/heads/main/extras/youtube-enhancer.png // @version 1.0 // @author exyezed // @namespace https://github.com/exyezed/youtube-enhancer/ // @supportURL https://github.com/exyezed/youtube-enhancer/issues // @license MIT // @match https://www.youtube.com/* // @grant none // ==/UserScript== (function() { 'use strict'; // Button Creation and Manipulation function createButton(text, iconName, id) { const button = document.createElement('button'); button.id = id; button.className = 'yt-spec-button-shape-next yt-spec-button-shape-next--tonal yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m'; button.style.display = 'inline-flex'; button.style.alignItems = 'center'; button.style.justifyContent = 'center'; button.style.minWidth = 'auto'; button.style.padding = '0 16px'; button.style.height = '36px'; button.style.fontSize = '14px'; button.style.lineHeight = '36px'; button.style.fontWeight = '500'; const icon = document.createElement('span'); icon.className = 'material-symbols-outlined'; icon.textContent = iconName; icon.style.marginRight = '4px'; icon.style.fontSize = '24px'; icon.style.fontWeight = '100'; const buttonText = document.createTextNode(text); button.appendChild(icon); button.appendChild(buttonText); return button; } function createButtonWrapper(button) { const buttonWrapper = document.createElement('div'); buttonWrapper.className = 'yt-flexible-actions-view-model-wiz__action'; buttonWrapper.appendChild(button); return buttonWrapper; } function addStatsButtons() { const targetElement = document.querySelector('yt-flexible-actions-view-model'); const lastAction = targetElement ? targetElement.querySelector('div.yt-flexible-actions-view-model-wiz__action:last-child') : null; if (lastAction && !document.querySelector('#YouTubeEnhancerChannelSecretStats')) { const secretStatsButton = createButton('Secret Stats', 'lock_open', 'YouTubeEnhancerChannelSecretStats'); const streamStatsButton = createButton('Stream Stats', 'cell_tower', 'YouTubeEnhancerStreamStats'); secretStatsButton.addEventListener('click', function() { const channelIdentifier = getChannelIdentifier(); if (channelIdentifier) { const statsUrl = `https://exyezed.vercel.app/stats/secret/${channelIdentifier}`; window.open(statsUrl, '_blank'); } else { alert('Could not determine channel identifier. Please try again on a channel page.'); } }); streamStatsButton.addEventListener('click', function() { const channelIdentifier = getChannelIdentifier(); if (channelIdentifier) { const statsUrl = `https://exyezed.vercel.app/stats/stream/${channelIdentifier}`; window.open(statsUrl, '_blank'); } else { alert('Could not determine channel identifier. Please try again on a channel page.'); } }); const secretStatsWrapper = createButtonWrapper(secretStatsButton); const streamStatsWrapper = createButtonWrapper(streamStatsButton); lastAction.insertAdjacentElement('afterend', streamStatsWrapper); lastAction.insertAdjacentElement('afterend', secretStatsWrapper); } } // Channel Identifier Functions function getChannelIdentifier() { const channelId = getChannelId(); if (channelId) return channelId; return getChannelHandle(); } function getChannelId() { const channelIdMeta = document.querySelector('meta[itemprop="channelId"]'); if (channelIdMeta) { return channelIdMeta.content; } const urlParams = new URLSearchParams(window.location.search); return urlParams.get('channel') || extractChannelIdFromUrl(); } function getChannelHandle() { const path = window.location.pathname; const matches = path.match(/\/@([^/]+)/); return matches ? matches[1] : null; } function extractChannelIdFromUrl() { const path = window.location.pathname; const matches = path.match(/\/(channel|user|c)\/([^/]+)/); return matches ? matches[2] : null; } // Utility Functions function addMaterialIconsStylesheet() { if (!document.querySelector('#material-icons-stylesheet')) { const link = document.createElement('link'); link.id = 'material-icons-stylesheet'; link.rel = 'stylesheet'; link.href = 'https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,150,0,0&icon_names=cell_tower,lock_open'; document.head.appendChild(link); } } function observePageChanges() { const observer = new MutationObserver((mutations) => { const targetElement = document.querySelector('yt-flexible-actions-view-model'); if (targetElement && targetElement.querySelector('div.yt-flexible-actions-view-model-wiz__action')) { addStatsButtons(); observer.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); } // Initialization function init() { if (window.location.pathname.includes('/channel/') || window.location.pathname.includes('/@') || window.location.pathname.includes('/c/') || window.location.pathname.includes('/user/')) { addMaterialIconsStylesheet(); observePageChanges(); } } // Run on initial page load init(); // Listen for YouTube spa navigation events window.addEventListener('yt-navigate-finish', init); })();