Game Votes w/ Decimals (Chrome Extension)

I made a simple chrome extension that shows game card like:dislike percentage values with 2 decimal points, rather than rounded to the nearest 0.

It works on the Games, Group, and Home pages.

Without extension

With extension

Why did I make this?
I wanted this because whenever I release large updates to my games, I like to know if it is shifting the over-all response from users, and in what direction. I have other mediums to collect user input however the majority of users will never contact me directly and will simply like/dislike the game. This saves me the hassle of manually calculating the more precise percentage whenever I want to know it. As games gather more and more total votes, the whole number % value rarely changes, and we must rely on a few decimal points to see actual changes. More popular games would benefit from more decimals, and I will add settings for that in the future if I get around to it.

Get it
You can install the extension here (external chrome web store link)

Disclaimer:
I’ve never attempted to make a chrome extension before, and have very limited knowledge when it comes to JavaScript. The extension uses Roblox web API endpoints to gather +/- votes and I cannot guarantee it’s accurate any further than those said API endpoints can. I’m not aware of any issues running the extension may or may not cause. If Roblox updates their HTML formatting for the game cards, the extension may fail and/or cause issues.

script source if you want to run it unpacked
var CONTAINER_CLASS = '.game-card-container'
var LINK_CLASS = ".game-card-link"
var DECIMAL_POINTS = 2;


var updated = [];
var parser = new DOMParser();

function MakeHttpObject() {
    try {return new XMLHttpRequest();}
    catch (error) {}
    try {return new ActiveXObject("Msxml2.XMLHTTP");}
    catch (error) {}
    try {return new ActiveXObject("Microsoft.XMLHTTP");}
    catch (error) {}

    throw new Error("Could not create HTTP request object.");
}


function Update(containerElement) {
    var linkElement = containerElement.querySelectorAll(LINK_CLASS)
    if (linkElement != null && linkElement[0] != null) {
        var linkReference = linkElement[0].href;
        if (linkReference != null) {
            var placeString = linkReference.match(/PlaceId=\d+/);
            if (placeString != null) {
                if (updated.includes(placeId) == false) {
                    var placeId = placeString[0].match(/\d+/)[0];
                    var request = MakeHttpObject();
                    if (request != null) {
                        request.open("GET", 'https://www.roblox.com/places/api-get-details?assetId=' + placeId, true);
                        request.send(null);
                        request.onreadystatechange = function() {
                            if (request.readyState == 4) {
                                var responseHtml = request.responseText;
                                var upVotes = parseInt(responseHtml.match(/"TotalUpVotes":\d+/)[0].replace(/"TotalUpVotes":/, ""), 10);
                                var downVotes = parseInt(responseHtml.match(/"TotalDownVotes":\d+/)[0].replace(/"TotalDownVotes":/, ""), 10);
                                var total = upVotes + downVotes;
                                var percent = ((upVotes / total) * 100).toFixed(DECIMAL_POINTS)
                                var percentElement = containerElement.querySelector(".vote-percentage-label")
                                if (percentElement != null) {
                                    percentElement.textContent = percent+"%"
                                }
                                updated.push(placeId);
                            }
                        }
                    }
                }
            }
        }
    }
}


function Run(){
    var divs = document.querySelectorAll(CONTAINER_CLASS);
    if (divs.length == 0) {
        setTimeout(Run, 3);
    } else {
        for (var i=0; i < divs.length; i++) {
            try {
                Update(divs[i]);
            }
            catch(err) {
                console.log("ERROR:", err);
            }
        }
    }
}

document.addEventListener("click", function() {
    Run();
})

Run();
15 Likes

Would there be any chance of a Firefox version to be made? It looks like it would be pretty simple to convert, but I don’t know how much different a Chrome extension is from a Firefox extension…

2 Likes

I believe you can add Chrome extensions to Firefox from the Chrome Web Store now.

2 Likes

just use brave, problem solved

From some googling (ironic isn’t it), it seems that FireFox and Chromium extenstions are coded differently. Although this could work (idk):

2 Likes

Sadly, it just tells me to get Google Chrome…

Firefox extensions and chrome extensions are not compatible since Firefox does not run on Chromium, it runs on Gecko. Firefox’s extension format is entirely separate from chrome’s and the APIs involved are different.

With browsers such as Opera, which are built on chromium, you can install Chrome extensions. Applications built in Electron (such as Discord) or NWJS actually rely on Chrome extensions sometimes (since both libraries are built on chromium).

As for the extension, this is pretty neat! I’ll definitely be using this despite its simplicity! :smile:
If you wanted to you could override the API functions used by Roblox to get game cards and their ratings. This would be more future-proof since Roblox JS APIs usually change less frequently than their site layout.

1 Like

Why does it read browsing history?

1 Like

I’m not sure why it says that. I had “tabs” and “activeTab” in the extension permissions from earlier but they are not needed. I removed those permissions and republished to chrome but it’ll take some time to be active. I’ll post the actual source code in the main post as well, so you can see it’s non-malicious and can run it unpacked if you so choose.

2 Likes

I’m not familiar with Roblox’s analytics; are rating trends over time not already tracked?

It doesn’t seem to work on profile pages.

Fun fact, you can use the Google api to download chrome extensions by id. You can then rename it to a zip file or use 7-zip to open it.

https://clients2.google.com/service/update2/crx?response=redirect&prodversion=49.0&x=id%3D ID_OF_EXTENSION_HERE %26installsource%3Dondemand%26uc

(You can also use a third party tool such as this one: https://chrome-extension-downloader.com/)

3 Likes

I know there used to be an extension called Chrome Store Foxified, which allowed installation of Chrome extensions on Firefox, but it seems to have been removed.