Recently I have created chrome extension called My Notes and as it received nice reviews, I have decided to create another one – Skip Ad.
I am also adding a tutorial this time, on how to create the extension.
Skip Ad
Skip Ad is a simple chrome extension that will skip YouTube ads for you, at https://www.youtube.com, so you can enjoy the content without interruptions.
I chose to create Skip Ad as it is something I would like to use personally, and is also simple to create, which makes it suitable to showcase how to create chrome extension.
After this article, you should not only have YouTube "without" ads but also be able to create chrome extension like this one.
Chapters
- 1 How to install Skip Ad
- 2 How Skip Ad looks
- 3 How Skip Ad works
- 4 How to create Skip Ad
- 5 Repository
1 How to install Skip Ad
The extension can be installed from the Web Store, a place where extensions are published.
Link:
https://chrome.google.com/webstore/detail/skip-ad/bimlffinhbdhgpomhngmnhidjgnfcnoc
2 How Skip Ad looks
Once the extension is installed, the following icon appears in the extensions list and the toolbar.
If you'd like to hide the icon from the toolbar, right-click the icon and select Hide in Chrome menu.
3 How Skip Ad works
After you open YouTube page, the extension will periodically check whether new ads are present and close them for you. If you already had some YouTube page open before the extension was installed, a simple page refresh will do.
The kind of ads that will be closed for you, and normally you would have to close manually by yourself, are shown below.
^^^ Video Ad can be closed with the Skip Ad button (single ad is shown), or Skip Ads button (multiple ads in the playlist).
^^^ Banner Ad can be closed with the X button.
Video Ad and Banner Ad can appear at the beginning of the video, or during the playback.
Buttons that are used to close the ad, are loaded with the ad, but in case of Video Ad, many times displayed after a delay. Skip Ad can skip the ad even before the button that closes the ad is shown. As a result, the ad may appear for a quick moment only.
4 How to create Skip Ad
4.1 Start by creating a new folder
We start by creating a new folder, to hold the extension files.
The name of the folder can be any. Usually, is the same as the name of the extension itself, just in kebab case (also called hyphen case).
Example: extension name Skip Ad => folder name skip-ad
Can two extensions have the same name, you might ask? The answer is yes.
Two extensions can have the same name, and the same code, still, they both can be installed because their unique ID will be different.
For learning purposes, let's call the extension differently – No More Ad.
Create a folder no-more-ad
.
4.2 Create manifest.json
Every file we create from now on will go inside the folder no-more-ad
.
Every extension has to have manifest.json
file. How you name and organize the other files, that's up to you.
Create manifest.json
with the following content:
{
"manifest_version": 2,
"name": "No More Ad",
"description": "Skips YouTube Ads.",
"version": "1.0"
}
Required keys: manifest_version
, name
and version
. Anything else is optional. More at: https://developer.chrome.com/extensions/manifest.
You might be surprised, but at this point, we have an extension that can be installed locally.
It won't do anything though, just appear in the list of extensions.
4.3 Add icon
Download the icon from the repository and put it inside the no-more-ad
folder.
Update manifest.json
to assign the icon.
{
"manifest_version": 2,
"name": "No More Ad",
"description": "Skips YouTube Ads.",
"version": "1.0",
"icons": { "128": "icon128.png" }
}
Now, as the extension has the icon, it will appear in the extensions list and the toolbar. You can try a different icon later.
4.4 Install extension locally
Although we have only manifest.json
file, the extension can be installed already and as we update the code, it can be manually reloaded, which is also a way to test if nothing got broken.
To install the extension, open the Extensions list first, either via the menu or by entering chrome://extensions
into the tab.
Now, click the Load unpacked button:
Navigate to no-more-ad
folder and click OPEN.
After the extension is loaded, you should see the following card:
The orange icon indicates, the extension is installed locally.
If you have installed Skip Ad, disable it temporarily so it doesn't interfere with No More Ad.
4.5 Time to skip the ads
Buttons that are used to skip the ads (3 How Skip Ad works) have CSS classes that make them easy to find.
CSS classes:
// Video Ad; "Skip Ad" or "Skip Ads" button
"ytp-ad-skip-button-text"
// Banner Ad; "X" button
"ytp-ad-overlay-close-button"
The code to skip the ads will be fairly simple. It should look for the buttons that can close the ad, and if it finds them, trigger the click()
.
Create youtube.js
now:
const click = (clazz) => {
const buttons = document.getElementsByClassName(clazz);
for (const button of buttons) {
button.click();
console.log("No More Ad");
}
}
setInterval(() => {
click("ytp-ad-skip-button-text");
click("ytp-ad-overlay-close-button");
}, 300);
console.log("No More Ad - Init");
You can try the code by opening YouTube and paste it to the console. Then, check some videos. If the ad gets closed, you should see in the console:
"No More Ad"
The last step of the puzzle is to get this code to the YouTube page without manually pasting it, that is, via the extension.
4.6 Setting content script
Content script can be either css, or js, or both. It is a term that, in other words, adds or modifies (as it can access the DOM) the content of the page, where it is inserted.
In our case, we intend to insert earlier created youtube.js
to the YouTube page.
This step is very easy, as it requires only to update manifest.json
:
{
"manifest_version": 2,
"name": "No More Ad",
"description": "Skips YouTube Ads.",
"version": "1.0",
"icons": { "128": "icon128.png" },
"content_scripts": [
{
"matches": ["https://*.youtube.com/*"],
"js": ["youtube.js"]
}
]
}
We have defined, that any page that matches a YouTube page, should include youtube.js
.
The content script defined via manifest.json
, is injected declaratively, which means, automatically. It is the easiest way of inserting a script to the other page.
Another way how to inject the content script, is programmatically. It is more complicated, but also more customizable.
Content scripts run in an isolated environment, therefore, they cannot influence other scripts. What they can do, as mentioned above, is access the DOM. And that's exactly what we needed.
More about content scripts is here: https://developer.chrome.com/extensions/content_scripts
4.7 Reload the extension
The extension we installed in the step 4.4 Install extension locally requires to be reloaded, to apply the changes.
This is easy to do by clicking the reload button.
If everything went well, no Errors should be shown.
4.8 Test the extension
Now, it's time to test the extension. Open a new YouTube page, or reload the existing.
To see that the content script was inserted, visit Sources:
In the console you can see:
"No More Ad - Init"
Check some YouTube videos. What you should experience is, the ads are getting closed automatically.
Check the console again. For every ad that gets closed, you should see:
"No More Ad"
You have now successfully created your extension.
5 Repository
You can check the extension here:
https://github.com/penge/skip-ad
I hope you enjoyed the article and learned new.
If you have any questions, I will gladly answer them.
If you'd like to see more tips or tricks, or series on this topic, let me know.
Now, let's enjoy this extension and start 2020 with fewer ads!
Cheers!
Top comments (13)
For those who would like to try the solution using Observer out of curiosity, although it seems not to be more performant nor work on pages where
#movie_player
is not present, here's the code:The solution needs some finishing where the comment is now. Take it as an exercise :)
performance would be better using a document observer instead of calling the function every 300 milliseconds
Hi!
You need to attach the Observer to the node. The "good" node would be
#movie_player
but it is not always present on the page, like in home page for example. You would then have to move the observer up the chain to the node that exists on each page. As content script is inserted on the first page load that might not have#movie_player
.If you let's say ignore point 1. (which you can't lol) and test it from
#movie_player
, then you still find yourself getting HUNDREDS of mutations (no attribute mutations included). You loop the mutations and filter them to only those that haveaddedNodes
. Then, you finally get to the container that encloses the ad, which is havingclassName
equal to"video-ads ytp-ad-module"
.The ad container that contains the enclosed ad, from point 2., is not the final destination. You still have to look for button inside that node as you don't get mutation for that button. So you end up using
getElementsByClassName
anyway.The execution time for the script using
setInterval
300ms, is around 0.00024ms every 300ms. That's literally nothing. 500k executions take about 120-130ms and that's tested on really cheap ARM CPU. This execution time, from the top of the tree, is same (no real difference), when compared to starting from#movie_player
.And so for these reasons, I doubt performance using the Observer would be any better.
PS: I'd like to see btw how this could be precisely measured. If you have the time to test it and support your statement with better result, that would be really cool.
Thanks for the response, I just checked how many times the Mutationobserver actually triggers while watching a video, and it's so much more than every 300ms! So yes, your method seems more efficient.
One thing I did, in order to hide the ads shown to the right oft the video, is a tiny bit of css code:
#player-ads {display:none !important}
The ads are still loaded, so the publisher should be paid (unlike with adblock, which blocks the request).
That's a good idea! Thanks!
I will add it to the next version.
Video overlay banners can also be handled the same way, as I found out they have a different container than Video ads. Hiding it via CSS would make it longer "visible" and publisher would get paid better as closing the banner is handled by youtube's
base.js
so it's probably tracked.Video ads would continue to be handled the same way, with a click.
The final code would be like this:
JS
CSS
Much better!
Thank you for this. I have created an extension for myself now.
Can we make if conditions to skip the ads like if the ads 15 secs longer suppose to skip at 7 sec or if the ad is 30 sec duration to skip at 15 sec or if the ad is longer than 1 minute or more it should skip at 30 sec...? please help me :)
Thanks very cool, didn't know it was this easy to make a simple extension
Cool!
I thought this would be something closer to AdBlock Plus!
How about AdSkip Plus? 😀
BUT THIS CODE WILL NOT SKIP UNSKIPPABLE ADS OF YOUTUBE ,IN WHICH THERE IS NO SKIP BUTTON.
LIKE THE IMAGE GIVEN BELOW
THIS IMAGE