Chrome Extension Black Friday Deal Tracker: A Developer’s Guide
Black Friday presents a unique challenge for developers and power users: deals appear across dozens of retailers, prices fluctuate hourly, and stock runs out within minutes. A well-built Chrome extension for tracking Black Friday deals can automate price monitoring, send instant notifications, and help you never miss a discount again. This guide walks through building a deal tracker extension from scratch.
Why Build a Deal Tracker Extension?
Commercial deal trackers often come with limitations—subscription fees, restricted notification channels, or retailer limitations. Building your own extension gives you complete control over which stores to monitor, how prices are tracked, and where notifications get sent.
The technical challenge is compelling. You need to handle dynamic content loaded via JavaScript, manage background tasks for price checking, implement cross-tab synchronization, and design an intuitive popup interface. These are real-world problems that translate to skills applicable across extension development.
Core Architecture
A Chrome deal tracker extension consists of three primary components:
- Content scripts that extract product data from retailer pages
- Background scripts managing price checks and notification dispatch
- Popup UI for viewing tracked items and configuring alerts
The manifest file defines these components and their permissions:
{
"manifest_version": 3,
"name": "Black Friday Deal Tracker",
"version": "1.0",
"permissions": [
"storage",
"notifications",
"activeTab",
"scripting"
],
"host_permissions": [
"*://*.amazon.com/*",
"*://*.bestbuy.com/*",
"*://*.walmart.com/*"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html"
}
}
Extracting Product Data
Each retailer structures product pages differently. You’ll need individual content scripts for major stores. Here’s a pattern for extracting product information:
// content-scripts/amazon.js
function extractProductData() {
const title = document.getElementById('productTitle')?.textContent?.trim();
const priceWhole = document.querySelector('.a-price-whole')?.textContent;
const priceFraction = document.querySelector('.a-price-fraction')?.textContent;
const originalPrice = document.querySelector('.a-text-price .a-offscreen')?.textContent;
return {
retailer: 'amazon',
title,
currentPrice: priceWhole && priceFraction
? parseFloat(priceWhole + '.' + priceFraction)
: null,
originalPrice: originalPrice ? parseFloat(originalPrice.replace(/[^0-9.]/g, '')) : null,
url: window.location.href,
asin: window.location.pathname.split('/dp/')[1]?.split('/')[0],
timestamp: Date.now()
};
}
chrome.runtime.sendMessage({ type: 'PRODUCT_DATA', data: extractProductData() });
This pattern extracts the product title, current price, and original price, then sends it to the background script for storage.
Managing Price Storage
Chrome’s storage API provides persistent data storage across browser sessions. Use it to maintain a list of tracked products:
// background.js
const STORAGE_KEY = 'tracked_deals';
async function addDeal(productData) {
const { [STORAGE_KEY]: deals = [] } = await chrome.storage.local.get(STORAGE_KEY);
const existingIndex = deals.findIndex(d => d.url === productData.url);
if (existingIndex >= 0) {
// Update existing deal with new price history
deals[existingIndex].priceHistory.push({
price: productData.currentPrice,
timestamp: Date.now()
});
} else {
// Add new deal
deals.push({
...productData,
priceHistory: [{ price: productData.currentPrice, timestamp: Date.now() }],
alertThreshold: null
});
}
await chrome.storage.local.set({ [STORAGE_KEY]: deals });
updateBadgeCount();
}
The price history array lets you calculate price drops and visualize trends over time.
Implementing Price Monitoring
For Black Friday, prices change rapidly. You need a mechanism to periodically check tracked URLs:
async function checkPrices() {
const { [STORAGE_KEY]: deals = [] } = await chrome.storage.local.get(STORAGE_KEY);
for (const deal of deals) {
try {
// Fetch product page
const response = await fetch(deal.url);
const html = await response.text();
// Extract current price (simplified)
const priceMatch = html.match(/"priceAmount":(\d+\.?\d*)/);
const currentPrice = priceMatch ? parseFloat(priceMatch[1]) : null;
if (currentPrice && currentPrice < deal.currentPrice) {
const discount = ((deal.currentPrice - currentPrice) / deal.currentPrice * 100).toFixed(1);
// Send notification for significant drops
if (discount >= 10) {
await sendNotification(deal, currentPrice, discount);
}
// Update stored price
deal.priceHistory.push({ price: currentPrice, timestamp: Date.now() });
deal.currentPrice = currentPrice;
}
} catch (error) {
console.error(`Failed to check ${deal.url}:`, error);
}
}
await chrome.storage.local.set({ [STORAGE_KEY]: deals });
}
// Check every 15 minutes during active shopping
chrome.alarms.create('priceCheck', { periodInMinutes: 15 });
chrome.alarms.onAlarm.addListener((alarm) => {
if (alarm.name === 'priceCheck') checkPrices();
});
The 15-minute interval balances between catching price drops and avoiding rate limiting from retailers.
Notification System
Chrome notifications work even when the browser runs in the background:
async function sendNotification(deal, newPrice, discountPercent) {
const notificationId = `deal-${deal.asin || Date.now()}`;
await chrome.notifications.create(notificationId, {
type: 'basic',
iconUrl: 'icons/icon-128.png',
title: `Price Drop: ${discountPercent}% Off!`,
message: `${deal.title}\nWas: $${deal.currentPrice} → Now: $${newPrice}`,
buttons: [
{ title: 'View Deal', iconUrl: 'icons/external.png' },
{ title: 'Dismiss' }
],
requireInteraction: true
});
// Handle button clicks
chrome.notifications.onButtonClicked.addListener((id, buttonIndex) => {
if (id === notificationId && buttonIndex === 0) {
chrome.tabs.create({ url: deal.url });
}
});
}
Building the Popup Interface
The popup provides quick access to tracked deals without leaving your current tab:
<!-- popup.html -->
<!DOCTYPE html>
<html>
<head>
<style>
body { width: 320px; font-family: system-ui, sans-serif; }
.deal { padding: 12px; border-bottom: 1px solid #eee; }
.deal-title { font-weight: 600; margin-bottom: 4px; }
.price-row { display: flex; gap: 8px; align-items: baseline; }
.original { text-decoration: line-through; color: #666; }
.current { color: #c00; font-weight: bold; font-size: 1.1em; }
.discount { background: #d4edda; color: #155724; padding: 2px 6px; border-radius: 4px; font-size: 0.85em; }
</style>
</head>
<body>
<div id="deals-list"></div>
<script src="popup.js"></script>
</body>
</html>
// popup.js
document.addEventListener('DOMContentLoaded', async () => {
const { [STORAGE_KEY]: deals = [] } = await chrome.storage.local.get(STORAGE_KEY);
const container = document.getElementById('deals-list');
if (deals.length === 0) {
container.innerHTML = '<p style="padding: 12px; color: #666;">No deals tracked yet. Visit a product page and click the extension icon to track.</p>';
return;
}
deals.forEach(deal => {
const latestPrice = deal.priceHistory[deal.priceHistory.length - 1].price;
const originalPrice = deal.originalPrice || latestPrice;
const discount = Math.round((originalPrice - latestPrice) / originalPrice * 100);
const dealEl = document.createElement('div');
dealEl.className = 'deal';
dealEl.innerHTML = `
<div class="deal-title">${deal.title.substring(0, 50)}...</div>
<div class="price-row">
<span class="original">$${originalPrice.toFixed(2)}</span>
<span class="current">$${latestPrice.toFixed(2)}</span>
${discount > 0 ? `<span class="discount">-${discount}%</span>` : ''}
</div>
`;
container.appendChild(dealEl);
});
});
Deployment Considerations
When distributing your extension through the Chrome Web Store, ensure you handle these practical concerns:
- Rate limiting: Implement exponential backoff if retailers block your requests
- Storage limits: Chrome provides 5MB free; for extensive tracking, consider cloud sync
- Authentication: For personalized alerts, implement OAuth for email or Discord webhooks
- Legal compliance: Review retailer terms of service regarding automated price checking
Extension Testing
Test your extension thoroughly before relying on it during Black Friday:
# Load unpacked extension for development
# 1. Navigate to chrome://extensions/
# 2. Enable Developer mode
# 3. Click Load unpacked
# 4. Select your extension directory
# Test price extraction on product pages
# Open DevTools → Console while on a retailer page
# Run: chrome.runtime.sendMessage({ type: 'TEST_EXTRACT' })
Check that content scripts inject correctly on each retailer domain and that the popup displays accurate price information.
Summary
Building a Chrome extension for Black Friday deal tracking combines practical web scraping, browser API mastery, and UI design. The architecture demonstrated here—content scripts for extraction, background scripts for monitoring, and a popup for user interaction—provides a solid foundation you can extend with cloud sync, multiple notification channels, or price prediction algorithms.
The skills developed through this project transfer directly to other extension types: inventory monitors, availability checkers, and price comparison tools. For developers looking to understand Chrome extension architecture deeply, a deal tracker is an excellent starting point.
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