Skip to main content

Chrome Extension Integration

Build Chrome extensions that reward users for productivity, content creation, and browser actions.

Overview

Reward users for:

  • Completing tasks
  • Using your extension
  • Content creation
  • Social sharing
  • Achieving productivity goals
  • Daily streaks

Quick Start

Manifest Configuration

// manifest.json (Manifest V3)
{
"manifest_version": 3,
"name": "My Rewards Extension",
"version": "1.0.0",
"permissions": [
"storage",
"activeTab"
],
"host_permissions": [
"https://api.loyalteez.app/*"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html",
"default_icon": "icon.png"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
]
}

Background Script (Service Worker)

// background.js
const LOYALTEEZ_API = 'https://api.loyalteez.app/loyalteez-api/manual-event';
const BRAND_ID = 'YOUR_BRAND_ID';

// Track event and reward user
async function rewardUser(userEmail, eventType, metadata = {}) {
try {
const response = await fetch(LOYALTEEZ_API, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
brandId: BRAND_ID,
eventType: eventType,
userEmail: userEmail,
domain: 'extension.yourdomain.com',
metadata: {
platform: 'chrome_extension',
extension_version: chrome.runtime.getManifest().version,
...metadata
}
})
});

const data = await response.json();

if (data.success) {
// Show notification
chrome.notifications.create({
type: 'basic',
iconUrl: 'icon.png',
title: 'Reward Earned!',
message: `You earned ${data.rewardAmount} LTZ!`
});
}

return data;
} catch (error) {
console.error('Reward failed:', error);
throw error;
}
}

// Listen for messages from popup/content scripts
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'reward_user') {
rewardUser(request.email, request.eventType, request.metadata)
.then(response => sendResponse({ success: true, data: response }))
.catch(error => sendResponse({ success: false, error: error.message }));
return true; // Keep channel open for async response
}
});

// Track extension install
chrome.runtime.onInstalled.addListener((details) => {
if (details.reason === 'install') {
chrome.storage.sync.get(['userEmail'], (result) => {
if (result.userEmail) {
rewardUser(result.userEmail, 'extension_installed', {
install_date: new Date().toISOString()
});
}
});
}
});
<!-- popup.html -->
<!DOCTYPE html>
<html>
<head>
<style>
body {
width: 300px;
padding: 20px;
font-family: Arial, sans-serif;
}
.reward-card {
background: #f5f5f5;
padding: 15px;
border-radius: 8px;
margin: 10px 0;
}
button {
background: #6C33EA;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
}
</style>
</head>
<body>
<h2>My Rewards Extension</h2>

<div id="user-info">
<label>Email:</label>
<input type="email" id="email" placeholder="[email protected]" />
<button id="save-email">Save</button>
</div>

<div class="reward-card">
<h3>Your Balance</h3>
<p id="balance">Loading...</p>
</div>

<div class="reward-card">
<h3>Quick Actions</h3>
<button id="daily-checkin">Daily Check-in</button>
<button id="share-extension">Share Extension</button>
</div>

<script src="popup.js"></script>
</body>
</html>
// popup.js
document.addEventListener('DOMContentLoaded', async () => {
// Load saved email
chrome.storage.sync.get(['userEmail'], (result) => {
if (result.userEmail) {
document.getElementById('email').value = result.userEmail;
}
});

// Save email
document.getElementById('save-email').addEventListener('click', () => {
const email = document.getElementById('email').value;
chrome.storage.sync.set({ userEmail: email }, () => {
alert('Email saved!');
});
});

// Daily check-in
document.getElementById('daily-checkin').addEventListener('click', async () => {
const email = document.getElementById('email').value;

chrome.runtime.sendMessage({
action: 'reward_user',
email: email,
eventType: 'daily_checkin',
metadata: { source: 'popup' }
}, (response) => {
if (response.success) {
alert('Check-in successful! Reward earned.');
}
});
});

// Share extension
document.getElementById('share-extension').addEventListener('click', async () => {
const email = document.getElementById('email').value;

// Copy share link
navigator.clipboard.writeText('https://chrome.google.com/webstore/...');

chrome.runtime.sendMessage({
action: 'reward_user',
email: email,
eventType: 'extension_shared',
metadata: { source: 'popup' }
});

alert('Share link copied! Reward earned.');
});
});

Content Script

// content.js
// Track user actions on web pages

// Example: Reward for productivity actions
function trackProductivityAction(action) {
chrome.storage.sync.get(['userEmail'], (result) => {
if (result.userEmail) {
chrome.runtime.sendMessage({
action: 'reward_user',
email: result.userEmail,
eventType: 'productivity_action',
metadata: {
action_type: action,
url: window.location.href,
timestamp: Date.now()
}
});
}
});
}

// Example: Detect task completion on specific sites
if (window.location.href.includes('task-completed')) {
trackProductivityAction('task_completed');
}

// Example: Track time spent on productive sites
let timeOnSite = 0;
setInterval(() => {
if (document.hasFocus()) {
timeOnSite += 60; // 60 seconds

if (timeOnSite >= 3600) { // 1 hour
trackProductivityAction('hour_productive');
timeOnSite = 0;
}
}
}, 60000); // Check every minute

Example Use Cases

Productivity Extension

// background.js - Track Pomodoro completions
let pomodoroCount = 0;

chrome.alarms.create('pomodoro', { periodInMinutes: 25 });

chrome.alarms.onAlarm.addListener((alarm) => {
if (alarm.name === 'pomodoro') {
pomodoroCount++;

chrome.storage.sync.get(['userEmail'], (result) => {
rewardUser(result.userEmail, 'pomodoro_completed', {
session_count: pomodoroCount,
date: new Date().toISOString()
});
});
}
});

Content Blocker Extension

// background.js - Reward for blocking distracting sites
const blockedSites = ['facebook.com', 'twitter.com', 'youtube.com'];
let blockedCount = 0;

chrome.webRequest.onBeforeRequest.addListener(
(details) => {
blockedCount++;

if (blockedCount % 10 === 0) { // Every 10 blocks
chrome.storage.sync.get(['userEmail'], (result) => {
rewardUser(result.userEmail, 'distractions_blocked', {
blocked_count: blockedCount
});
});
}

return { cancel: true };
},
{ urls: blockedSites.map(site => `*://${site}/*`) },
['blocking']
);

Reading Extension

// content.js - Track reading time and articles read
let readingTime = 0;
let articlesRead = 0;

// Detect article completion
const observer = new MutationObserver(() => {
const scrollPercentage = (window.scrollY + window.innerHeight) / document.body.scrollHeight;

if (scrollPercentage > 0.9 && !document.body.dataset.articleRead) {
document.body.dataset.articleRead = 'true';
articlesRead++;

chrome.runtime.sendMessage({
action: 'reward_user',
email: userEmail,
eventType: 'article_read',
metadata: {
article_url: window.location.href,
articles_read_total: articlesRead
}
});
}
});

observer.observe(document.body, { childList: true, subtree: true });

Shopping Extension

// content.js - Reward for price comparison
function detectPurchase() {
// Detect thank you / order confirmation pages
const thankYouIndicators = [
'/thank-you',
'/order-confirmation',
'order-complete'
];

const isThankYouPage = thankYouIndicators.some(indicator =>
window.location.href.includes(indicator)
);

if (isThankYouPage) {
chrome.storage.sync.get(['userEmail'], (result) => {
chrome.runtime.sendMessage({
action: 'reward_user',
email: result.userEmail,
eventType: 'purchase_completed',
metadata: {
merchant: window.location.hostname,
date: new Date().toISOString()
}
});
});
}
}

detectPurchase();

Advanced Features

Daily Streak Tracking

// background.js
async function trackDailyStreak(userEmail) {
const { lastCheckin, streak } = await chrome.storage.sync.get(['lastCheckin', 'streak']);

const today = new Date().toDateString();
const yesterday = new Date(Date.now() - 86400000).toDateString();

let newStreak = 1;

if (lastCheckin === yesterday) {
newStreak = (streak || 1) + 1;
} else if (lastCheckin !== today) {
newStreak = 1;
}

await chrome.storage.sync.set({
lastCheckin: today,
streak: newStreak
});

// Reward based on streak
const bonusMultiplier = Math.min(newStreak / 7, 3); // Up to 3x bonus
await rewardUser(userEmail, 'daily_checkin', {
streak: newStreak,
bonus_multiplier: bonusMultiplier
});
}

Achievement System

// background.js
const ACHIEVEMENTS = {
'first_day': { requirement: 1, reward: 50, name: 'First Day' },
'week_streak': { requirement: 7, reward: 200, name: 'Week Warrior' },
'month_streak': { requirement: 30, reward: 1000, name: 'Monthly Master' },
'hundred_actions': { requirement: 100, reward: 500, name: 'Century' }
};

async function checkAchievements(userEmail, metric, value) {
const { unlockedAchievements = [] } = await chrome.storage.sync.get('unlockedAchievements');

for (const [key, achievement] of Object.entries(ACHIEVEMENTS)) {
if (value >= achievement.requirement && !unlockedAchievements.includes(key)) {
unlockedAchievements.push(key);
await chrome.storage.sync.set({ unlockedAchievements });

await rewardUser(userEmail, 'achievement_unlocked', {
achievement: achievement.name,
reward: achievement.reward
});

chrome.notifications.create({
type: 'basic',
iconUrl: 'icon.png',
title: 'Achievement Unlocked!',
message: `${achievement.name}: ${achievement.reward} LTZ earned!`
});
}
}
}

Offline Support

// background.js
const pendingRewards = [];

async function rewardUserOffline(userEmail, eventType, metadata) {
if (!navigator.onLine) {
pendingRewards.push({ userEmail, eventType, metadata, timestamp: Date.now() });
await chrome.storage.local.set({ pendingRewards });
return;
}

return await rewardUser(userEmail, eventType, metadata);
}

// Process pending rewards when online
window.addEventListener('online', async () => {
const { pendingRewards = [] } = await chrome.storage.local.get('pendingRewards');

for (const reward of pendingRewards) {
try {
await rewardUser(reward.userEmail, reward.eventType, reward.metadata);
} catch (error) {
console.error('Failed to process pending reward:', error);
}
}

await chrome.storage.local.set({ pendingRewards: [] });
});

Testing

// Test mode
const IS_TEST = true;
const TEST_EMAIL = '[email protected]';

if (IS_TEST) {
console.log('Extension running in test mode');

// Use test API
const LOYALTEEZ_API = 'https://api-test.loyalteez.app/loyalteez-api/manual-event';
}

Publishing

Chrome Web Store

  1. Prepare assets

    • Icon: 128x128px
    • Screenshots: 1280x800px
    • Promotional images
  2. Update manifest

    • Set correct permissions
    • Add privacy policy URL
    • Update version number
  3. Submit for review

Best Practices

1. Request Minimal Permissions

{
"permissions": [
"storage" // Only what you need
],
"optional_permissions": [
"tabs" // Request when needed
]
}

2. Handle Errors Gracefully

async function safeReward(userEmail, eventType, metadata) {
try {
return await rewardUser(userEmail, eventType, metadata);
} catch (error) {
console.error('Reward failed:', error);
// Queue for retry
queueReward(userEmail, eventType, metadata);
}
}

3. Respect User Privacy

// Only track with user consent
async function requestTrackingConsent() {
const { trackingConsent } = await chrome.storage.sync.get('trackingConsent');

if (!trackingConsent) {
// Show consent dialog
const consent = await showConsentDialog();
await chrome.storage.sync.set({ trackingConsent: consent });
return consent;
}

return trackingConsent;
}

Support