Search code examples
javascriptgreasemonkeytampermonkey

How can I redirect to my youtube subscription page in Greasemonkey?


I don't want to see distracting youtube recommendations on my start screen, I just want to be redirected to my subscription page whenever I go to the / path of youtube. I tried to redesign the youtube page in my DOM by using javascript to redirect from the / path to the /feed/subscriptions path automatically.

I created the following script, which unfortunately only works on page reload.

// ==UserScript==
// @name        YT redir /home -> /sub
// @match       https://www.youtube.com/*
// @grant       none
// @run-at      document-start
// @version     1.0
// @author      -
// @description 5/30/2020, 12:16:13 PM
// ==/UserScript==

var current_location = location.pathname;
if(current_location == "/"){
     window.location.replace("https://youtube.com/feed/subscriptions")
}

I expected this script to also work when I browse youtube and click on the home or youtube logo button. However it only works on page reload.

How can I make this script work without having to reload youtube?

To work around this problem to achieve the same goal I tried to just replace the href attribute of the home button and the logo button.

// ==UserScript==
// @name        YT test
// @match       https://www.youtube.com/*
// @grant       none
// @run-at      document-start
// @version     1.0
// @author      -
// @description 5/30/2020, 12:16:13 PM
// ==/UserScript==

document.getElementById("endpoint").href="/feed/subscriptions";
document.getElementById("endpoint").removeAttribute('class');
document.getElementById("logo").href="/feed/subscriptions";
document.getElementById("logo").removeAttribute('class');

However, although these commands work in the JS console, they do not take effect as greasemonkey script even if I put the run-at attribute to document-end.

How can I make these changes automatic via Greasemonkey?


Solution

  • Problems:

    1. YouTube pages have multiple elements with the same id in one document, which is a violation of the HTML standard, so document.getElementById("logo") will find the wrong one. You can use document.querySelector('a#logo') instead.

    2. The page is built dynamically using JavaScript so the elements may appear long time after DOMContentLoaded event has occurred. You can use MutationObserver (may be resource-consuming) or setTimeout/setInterval (not precise).

    3. YouTube site is a SPA (single page application) which imitates navigation by using History API but userscripts are executed only on real navigation.


    Solution:

    There could be many solutions, arguably, but I suggest using a simple click listener in capture phase (the third parameter of addEventListener is true) so that you don't have to depend on the exact selector for the element, which may change unpredictably when the site code updates in the future.

    // ==UserScript==
    // @name        YT redir /home -> /sub
    // @match       https://www.youtube.com/*
    // @grant       none
    // @run-at      document-start
    // ==/UserScript==
    
    if (location.pathname === '/') {
      location.pathname = '/feed/subscriptions';
    }
    window.addEventListener('click', e => {
      const a = e.target.closest('a');
      if (a && a.href === 'https://www.youtube.com/') {
        a.pathname = '/feed/subscriptions';
        a.className = '';
      }
    }, true);