Building a Chrome Extension for Flash Sale Notifications
Flash sales create urgency and drive conversions, but catching them requires constant vigilance. As a developer or power user, you can automate this process by building a Chrome extension that monitors target pages and alerts you the moment a deal appears. This guide walks you through creating a flash sale notification extension from scratch.
Understanding the Architecture
A flash sale notification system consists of three core components: the content script that scans page content, a background service worker that manages the monitoring logic, and a notification system that alerts users. Chrome extensions provide all these capabilities through their extension API.
The content script runs in the context of web pages you visit, allowing it to read the DOM and detect sale indicators. The background worker maintains state, schedules periodic checks, and coordinates notifications across tabs. This separation keeps your extension responsive without draining resources.
Setting Up the Manifest
Every Chrome extension begins with a manifest file. For a flash sale monitor, you need permissions to access tabs, execute scripts, and display notifications:
{
"manifest_version": 3,
"name": "Flash Sale Detector",
"version": "1.0",
"description": "Monitors pages for flash sales and notifies you instantly",
"permissions": [
"tabs",
"notifications",
"storage",
"activeTab",
"scripting"
],
"host_permissions": [
"<all_urls>"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content.js"],
"run_at": "document_idle"
}]
}
This manifest grants the extension access to all URLs, which you should narrow in production to only the sites you actually want to monitor.
Building the Content Script
The content script is your detection engine. It scans the page for sale-related elements and communicates findings to the background worker:
// content.js
const SALE_INDICATORS = [
'flash sale',
'limited time',
'ending soon',
'discount',
'% off',
'deal',
'offer ends'
];
function detectFlashSale() {
const pageText = document.body.innerText.toLowerCase();
const pageTitle = document.title.toLowerCase();
const combined = pageText + ' ' + pageTitle;
const foundIndicators = SALE_INDICATORS.filter(
indicator => combined.includes(indicator.toLowerCase())
);
if (foundIndicators.length > 0) {
const priceElements = document.querySelectorAll('[class*="price"], [class*="sale"], .discount');
const prices = Array.from(priceElements)
.map(el => el.innerText)
.filter(text => /\$[\d,]+\.?\d*/.test(text));
return {
detected: true,
indicators: foundIndicators,
prices: prices.slice(0, 5),
url: window.location.href,
title: document.title
};
}
return { detected: false };
}
// Report findings to background
const result = detectFlashSale();
if (result.detected) {
chrome.runtime.sendMessage({
type: 'FLASH_SALE_DETECTED',
data: result
});
}
This script searches for common sale terminology and extracts potential prices. You can customize the SALE_INDICATORS array to target specific types of deals or sites.
Implementing the Background Worker
The background worker receives notifications from content scripts and displays alerts to users. It also manages user preferences and tracks monitored pages:
// background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'FLASH_SALE_DETECTED') {
handleFlashSaleDetected(message.data, sender.tab);
}
});
function handleFlashSaleDetected(data, tab) {
// Check if user wants notifications for this site
chrome.storage.local.get(['monitoredDomains', 'notificationSettings'], (result) => {
const domain = new URL(data.url).hostname;
const monitoredDomains = result.monitoredDomains || [];
// Only notify for monitored domains or if monitoring all
if (monitoredDomains.length === 0 || monitoredDomains.includes(domain)) {
showNotification(data, tab.id);
}
});
}
function showNotification(data, tabId) {
const priceList = data.prices.join(', ') || 'Check site for prices';
chrome.notifications.create({
type: 'basic',
iconUrl: 'icons/icon-128.png',
title: '⚡ Flash Sale Detected!',
message: `${data.title}\nFound: ${data.indicators.join(', ')}\nPrices: ${priceList}`,
buttons: [
{ title: 'View Now' },
{ title: 'Dismiss' }
],
priority: 1
}, (notificationId) => {
// Store the tab ID for button clicks
chrome.storage.local.set({
[`notification_${notificationId}`]: tabId
});
});
}
// Handle notification button clicks
chrome.notifications.onButtonClicked.addListener((notificationId, buttonIndex) => {
chrome.storage.local.get([`notification_${notificationId}`], (result) => {
const tabId = result[`notification_${notificationId}`];
if (buttonIndex === 0 && tabId) {
chrome.tabs.update(tabId, { active: true });
}
});
chrome.notifications.clear(notificationId);
});
This worker displays rich notifications with action buttons. Users can click to view the deal or dismiss the alert.
Adding Periodic Monitoring
Content scripts only run when you visit a page. For continuous monitoring, you need periodic checks using the Chrome Alarm API:
// background.js - add to background.js
chrome.alarms.create('periodicCheck', {
periodInMinutes: 5
});
chrome.alarms.onAlarm.addListener((alarm) => {
if (alarm.name === 'periodicCheck') {
checkActiveTabs();
}
});
async function checkActiveTabs() {
const tabs = await chrome.tabs.query({ active: true, currentWindow: true });
for (const tab of tabs) {
try {
const results = await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: detectFlashSale
});
if (results[0].result?.detected) {
handleFlashSaleDetected(results[0].result, tab);
}
} catch (error) {
// Script may fail on restricted pages
console.log('Could not scan tab:', error.message);
}
}
}
This adds a 5-minute polling interval that checks the currently active tab for deals even when you’re not actively looking.
Persisting User Preferences
Allow users to configure which domains to monitor and notification preferences:
// options.js
function saveSettings() {
const domains = document.getElementById('monitoredDomains').value
.split('\n')
.map(d => d.trim())
.filter(d => d.length > 0);
const settings = {
monitoredDomains: domains,
notificationSettings: {
sound: document.getElementById('enableSound').checked,
desktop: document.getElementById('enableDesktop').checked
}
};
chrome.storage.local.set(settings, () => {
document.getElementById('status').textContent = 'Settings saved!';
});
}
document.getElementById('saveButton').addEventListener('click', saveSettings);
// Load saved settings on page load
chrome.storage.local.get(['monitoredDomains', 'notificationSettings'], (result) => {
if (result.monitoredDomains) {
document.getElementById('monitoredDomains').value = result.monitoredDomains.join('\n');
}
});
Advanced: Price Drop Detection
Beyond detecting sales, you can track price changes over time:
// price-tracker.js
class PriceTracker {
constructor() {
this.priceHistory = new Map();
}
recordPrice(url, price, timestamp = Date.now()) {
if (!this.priceHistory.has(url)) {
this.priceHistory.set(url, []);
}
const history = this.priceHistory.get(url);
history.push({ price, timestamp });
// Keep last 100 entries per URL
if (history.length > 100) {
history.shift();
}
chrome.storage.local.set({ priceHistory: Object.fromEntries(this.priceHistory) });
}
getPriceChange(url) {
const history = this.priceHistory.get(url);
if (!history || history.length < 2) return null;
const oldest = history[0].price;
const latest = history[history.length - 1].price;
return {
oldPrice: oldest,
newPrice: latest,
change: latest - oldest,
percentChange: ((latest - oldest) / oldest) * 100
};
}
}
Track historical prices and alert users when items drop below a threshold they set.
Deployment and Testing
When your extension is ready, load it in Chrome by navigating to chrome://extensions/, enabling Developer Mode, and clicking “Load unpacked.” Select your extension directory.
Test thoroughly across different sites and page loads. Monitor performance impact—the content script runs on every page, so optimize by minimizing DOM queries and using efficient selectors.
For distribution through the Chrome Web Store, you’ll need to prepare screenshots, write a detailed description, and pay a one-time developer registration fee. Your extension must pass Google’s review process before publishing.
Conclusion
Building a flash sale notification extension combines DOM manipulation, Chrome’s extension APIs, and user preference management. Start with basic detection and gradually add features like price tracking, scheduled monitoring, and configurable alerts. The extension you build can save hours of manual browsing and help you never miss a deal again.
Related Reading
- Claude Code for Beginners: Complete Getting Started Guide
- Best Claude Skills for Developers in 2026
- Claude Skills Guides Hub
Built by theluckystrike — More at zovo.one