December 13, 2015
A while back I had an idea for a chrome extension that would block any posts about Kim Kardashian from my News Feed. Often times pop-culture can be akin to a parasite, sucking up people’s attention, thoughts, energy, fears, self-worth, or even dignity just to thrive.
Am I being a bit over dramatic? Yes. Can you tell that I don’t like Kim Kardashian? Yes. But I had a solution that disappointed my inner-Socrates: selective ignorance. Ignore the stuff that I really, truly, never wish to see again, that has no value, and I’ll be better off. Thus, I wrote Blissfully- my first Chrome Extension. Blissfully lets users enter keywords/phrases/#hashtags that they have no interest in seeing appear on their Facebook News Feeds, and then hides them from sight.
This essay/article is just a big summary of what went into this plugin, I hope you enjoy. If you are looking to write your first chrome plugin, feel free to send me an email (found on my homepage), and I can elaborate a little on some things to be aware of. Anyway, here’s my summary:
Since this was a Chrome extension, I decided to go with a slightly material design approach (if you download the plugin, notice the button hover and the input field label animations, which are common material design patterns). I’m not sure if I succeeded, but I made a conscious decision to have the button and blacklist to follow a material aesthetic (even the blacklist follows official Google padding guidelines).
The chrome extension icon only shows up when the user is on Facebook because that’s the only time they will ever use it. The user can also see which topics they are blocking, but only if they explicitly choose to do so (by clicking “view blacklist”). Why am I making special note of this? Because if you have no interest in seeing status updates about a specific person, then why should you see their name every time you open the plugin? This is a mistake a few other Facebook filter plugins made- displaying the blacklist upon clicking the popup.
Another important design decision I made was to NOT let Blissfully visually indicate on a user’s FB news feed that something has been blocked, and it will not leave a message in place of where the post should have been to let the user know it did its job. That only serves the Ego of the developer, reminding users “Hey I’m working!”, when in reality, a user should be completely oblivious. Instead, Blissfully keeps a counter that will let a user know, when they click on Blissfully, the total number of posts that it has successfully blocked from sight. If I replaced each post in a feed that was about ____ (insert keyword) with “THIS POST IS ABOUT ____, AND IS THEREFORE BLOCKED”, that would be pretty silly, because the whole point is to avoid having to think of ____ ever again. Cruel, I know, but again, this was another mistake that was made by other FB feed filters.
Synced Chrome Storage The data that Blissfully stores uses Chrome’s Storage Sync API, allowing users to seamlessly sync their keyword blacklists across multiple Chrome browsers.
Use of the Module Design Pattern I used a module pattern in the content script that publicly exposes a few functions which are called by the popup’s script. This wasn’t necessary, as I could have used Chrome’s messaging API to share values between the script, but I was not aware of those APIs at the time and chose to use this pattern (see ‘Lessons Learned’).
Use of Mutation Observer API I elaborate on this in the following section, but I chose to use the newly added Mutation Observer API (only supported by Chrome and Firefox at this time), which allows the plugin to observe the DOM and run a callback function whenever a new element is added to the DOM. I thought this was pretty cool and later learned that this is also asynchronous, which made my plugin pretty speedy.
Blissfully is cool because it is simple to use and also one of the more technically efficient and light-weight Facebook news feed filter plugins that I’ve found on the Chrome store at this time. While other plugins rely on jQuery, Blissfully is Vanilla, saving a few extra kilobytes. I know this doesn’t really make much of a difference, and it wasn’t the reason why I wrote it in Vanilla JS, but it does feel good when you avoid unnecessary bloat.
While other plugins search the entire DOM for a keyword each time a search function is called, or search FB’s DOM on each mouse scroll, Blissfully only searches the elements on a page that were added to the DOM rather than scan the entire DOM tree each time or scanning the DOM on every single page scroll despite the DOM not having changed. It does this by using a browser API called Mutation Observer. I hope I haven’t misspoken by saying that this plugin is more efficient because it uses Mutation Observer, but based on my current understanding of how Mutation Observer works, Mutation Observer’s asynchronousity is useful in this situation.
There are APIs for Extensions that allow message sending between different parts of the app, and to sync storage data, but again, when I knew little about each one, and when I rushed into attempting to use them without knowing key facts and details on their functions, it unneccessarily cost me time.
Read the docs before going to Stack Overflow, and take more time upfront trying to understand them. By skipping the docs and going straight to SO for a specific answer, I came across some answers that left out key details of how APIs work that ended up costing me time in the long run. This could have been avoided if I spent a little extra time up front reading through the docs. Jumping in is exciting, but sometimes a bit more theory first can be more effective.
Get an overview of a new platform’s architecture before jumping right in. Had I known a bit more about Chrome extensions being made up of ‘isolated worlds’ that all live separately from each other, I could have avoided some headaches and confusion on why some data was not loading like intended. I don’t like sitting through tutorials and like getting my hands dirty right away, but maybe spending a bit more time with a broad overview upfront or a ‘getting started’ tutorial could have been well-worth it.
If you made it this far, thank you for reading. Feel free to reach me on LinkedIn or on twitter @hagepat!
I'm Patrick El-Hage and I live and work in San Francisco. I like to hang on Twitter.