diff --git a/package-lock.json b/package-lock.json
index 5f9b1b51..68b87d25 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7109,9 +7109,9 @@
       }
     },
     "node_modules/envinfo": {
-      "version": "7.11.1",
-      "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.1.tgz",
-      "integrity": "sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==",
+      "version": "7.12.0",
+      "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.12.0.tgz",
+      "integrity": "sha512-Iw9rQJBGpJRd3rwXm9ft/JiGoAZmLxxJZELYDQoPRZ4USVhkKtIcNBPw6U+/K2mBpaqM25JSV6Yl4Az9vO2wJg==",
       "dev": true,
       "bin": {
         "envinfo": "dist/cli.js"
diff --git a/src/background.js b/src/background.js
index db754707..6f8be63c 100644
--- a/src/background.js
+++ b/src/background.js
@@ -2,13 +2,13 @@
 // Handles communication between the extension and the content script as well as Firebase interactions
 import { configSync, setSyncStorageValue } from "./chromeStorage.js";
 import { isFirefox, firebaseConfig } from "./config.js";
-import { initializeApp } from "firebase/app";
+import { hasActiveSubscriptionRole } from "./stripe.js";
+import { getApp, getApps, initializeApp } from "firebase/app";
 import { getDatabase, ref, child, update, get, remove } from "firebase/database";
 
 // ---------- Initialization/Chrome event listeners ----------
 // Check whether a new version was installed
 async function initExtension() {
-	// TODO: Change the extension icon if the user is subscribed to Shuffle+
 	const manifestData = chrome.runtime.getManifest();
 	if (configSync.previousVersion === null) {
 		console.log(`Extension was installed for the first time (v${manifestData.version})`);
@@ -25,10 +25,28 @@ async function initExtension() {
 		await handleExtensionUpdate(manifestData, configSync.previousVersion);
 	}
 
+	await checkShufflePlusStatus();
 	checkLocalStorageCapacity();
 }
+
 await initExtension();
 
+// On every startup, we check the claim roles for the user
+async function checkShufflePlusStatus() {
+	// TODO: If the user has not yet been introduced to Shuffle+, open the introduction page
+	if (await hasActiveSubscriptionRole()) {
+		console.log("User has an active Shuffle+ subscription.");
+		chrome.action.setIcon({
+			path: {
+				"16": chrome.runtime.getURL("icons/icon-16-white.png"),
+				"32": chrome.runtime.getURL("icons/icon-32-white.png"),
+				"48": chrome.runtime.getURL("icons/icon-48-white.png"),
+				"128": chrome.runtime.getURL("icons/icon-128-white.png")
+			}
+		});
+	}
+}
+
 // Make sure we are not using too much local storage
 async function checkLocalStorageCapacity() {
 	// If over 90% of the storage quota for playlists is used, remove playlists that have not been accessed in a long time
@@ -197,7 +215,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
 });
 
 // ---------- Firebase ----------
-const app = initializeApp(firebaseConfig);
+const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();
 const db = getDatabase(app);
 
 async function updatePlaylistInfoInDB(playlistId, playlistInfo, overwriteVideos) {
diff --git a/src/googleOauth.js b/src/googleOauth.js
index 9d282caf..70865f1b 100644
--- a/src/googleOauth.js
+++ b/src/googleOauth.js
@@ -2,11 +2,11 @@
 import { setSyncStorageValue } from "./chromeStorage.js";
 import { isFirefox, firebaseConfig } from "./config.js";
 import { hasActiveSubscriptionRole } from "./stripe.js";
-import { initializeApp } from "firebase/app";
+import { getApp, getApps, initializeApp } from "firebase/app";
 import { getFirestore, doc, getDoc, setDoc, deleteDoc } from "firebase/firestore";
 import { getAuth, onAuthStateChanged, GoogleAuthProvider, signInWithCredential } from "firebase/auth";
 
-const app = initializeApp(firebaseConfig);
+const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();
 const db = getFirestore(app);
 const auth = getAuth(app);
 
@@ -24,7 +24,7 @@ export async function getUser(localOnly, allowSelfRevoke, signupIfNull) {
 		console.log("No local user info found.");
 		return null;
 	} else if (googleOauth || (googleOauth == null && signupIfNull)) {
-		console.log("Attempting to sign up using Google Oauth.");
+		console.log("Attempting to sign in using Google Oauth (will attempt to sign up if no user exists).");
 		// This will also refresh the access token if it has expired
 		return await googleLogin(allowSelfRevoke);
 	} else {
diff --git a/src/html/shufflePlus.js b/src/html/shufflePlus.js
index 83b4212d..9fc15273 100644
--- a/src/html/shufflePlus.js
+++ b/src/html/shufflePlus.js
@@ -102,8 +102,15 @@ async function setDomElementEventListeners(domElements) {
 			domElements.googleRevokeAccessButtonDiv.classList.remove("hidden");
 			domElements.manageSubscribtionButtonDiv.classList.remove("hidden");
 			await setSubscriptionUI(domElements, user);
-			// TODO: If the user is logged in and subscribed, change the extension icon, e.g.:
-			chrome.action.setIcon({ path: chrome.runtime.getURL("icons/icon-128-white.png") });
+
+			chrome.action.setIcon({
+				path: {
+					"16": chrome.runtime.getURL("icons/icon-16-white.png"),
+					"32": chrome.runtime.getURL("icons/icon-32-white.png"),
+					"48": chrome.runtime.getURL("icons/icon-48-white.png"),
+					"128": chrome.runtime.getURL("icons/icon-128-white.png")
+				}
+			});
 		} else {
 			domElements.googleLoginButton.textContent = `Login failed with error: ${user.code ? user.code : "Unknown Error"}`;
 			domElements.googleLoginSuccessDiv.classList.add("hidden");
diff --git a/src/stripe.js b/src/stripe.js
index 22f62add..9b88607b 100644
--- a/src/stripe.js
+++ b/src/stripe.js
@@ -1,11 +1,11 @@
 // Contains logic for interacting with Stripe for payment handling
 import { firebaseConfig } from "./config.js";
 import { getUser } from "./googleOauth.js";
-import { initializeApp } from "firebase/app";
+import { getApp, getApps, initializeApp } from "firebase/app";
 import { getFirestore, query, collection, where, getDocs, addDoc, onSnapshot, FieldPath } from "firebase/firestore";
 import { getAuth } from "firebase/auth";
 
-const app = initializeApp(firebaseConfig);
+const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();
 const db = getFirestore(app);
 
 // Get products and pricing information from Firestore/Stripe
@@ -139,13 +139,14 @@ export async function getSubscriptions(user = null, activeOnly = true) {
 }
 
 // This will return shufflePlus if the user has an active subscription
-async function getStripeRole() {
-	const decodedToken = await getAuth().currentUser.getIdTokenResult();
+async function getStripeRole(user = null) {
+	user ??= await getUser(false, true, false);
+	const decodedToken = await getAuth().currentUser?.getIdTokenResult();
 	return decodedToken.claims?.stripeRole ?? null;
 }
 
 // TODO: Use this, as it is probably faster and cheaper than querying Firestore
-export async function hasActiveSubscriptionRole() {
-	const stripeRole = await getStripeRole();
+export async function hasActiveSubscriptionRole(user = null) {
+	const stripeRole = await getStripeRole(user);
 	return stripeRole === "shufflePlus";
 }
diff --git a/static/icons/icon-128-white.png b/static/icons/icon-128-white.png
new file mode 100644
index 00000000..0694ea6f
Binary files /dev/null and b/static/icons/icon-128-white.png differ
diff --git a/static/icons/icon-16-white.png b/static/icons/icon-16-white.png
new file mode 100644
index 00000000..8b59ed22
Binary files /dev/null and b/static/icons/icon-16-white.png differ
diff --git a/static/icons/icon-32-white.png b/static/icons/icon-32-white.png
new file mode 100644
index 00000000..7186be0c
Binary files /dev/null and b/static/icons/icon-32-white.png differ
diff --git a/static/icons/icon-48-white.png b/static/icons/icon-48-white.png
new file mode 100644
index 00000000..ac4407aa
Binary files /dev/null and b/static/icons/icon-48-white.png differ