📋 Table of Contents
Why Visual Monitoring?
Traditional monitoring checks if your website is "up" - but what about visual issues? A deployment might succeed while:
- CSS fails to load, making your site look broken
- Third-party scripts break your layout
- Content changes unexpectedly
- Mobile view is completely broken
Visual monitoring with screenshots catches these issues before users report them.
📊 Stat: Visual bugs account for 23% of all production issues, yet most monitoring tools miss them entirely.
System Architecture
Here's a simple architecture for screenshot-based monitoring:
- Scheduler - Runs every 5-15 minutes (cron, GitHub Actions, etc.)
- Screenshot API - Captures current state of your pages
- Storage - Saves screenshots with timestamps
- Comparison - Detects visual changes
- Alerting - Notifies you of issues (Slack, email, etc.)
Implementation
Step 1: Define Pages to Monitor
const PAGES_TO_MONITOR = [
{ name: 'Homepage', url: 'https://yoursite.com/', device: 'desktop' },
{ name: 'Homepage Mobile', url: 'https://yoursite.com/', device: 'mobile' },
{ name: 'Pricing', url: 'https://yoursite.com/pricing', device: 'desktop' },
{ name: 'Login', url: 'https://yoursite.com/login', device: 'desktop' },
];
Step 2: Capture Screenshots
const fs = require('fs');
const path = require('path');
async function captureScreenshots() {
const API_KEY = process.env.SNAPAPI_KEY;
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
for (const page of PAGES_TO_MONITOR) {
const params = new URLSearchParams({
url: page.url,
api_key: API_KEY,
device: page.device,
response: 'binary'
});
const response = await fetch(
`https://snapapi.alterra-solutions.com/v1/screenshot?${params}`
);
const buffer = await response.arrayBuffer();
const filename = `${page.name.toLowerCase().replace(/\s+/g, '-')}_${timestamp}.png`;
fs.writeFileSync(
path.join('./screenshots', filename),
Buffer.from(buffer)
);
console.log(`✅ Captured: ${page.name}`);
}
}
captureScreenshots();
Step 3: Compare Screenshots
const pixelmatch = require('pixelmatch');
const { PNG } = require('pngjs');
async function compareScreenshots(current, previous) {
const img1 = PNG.sync.read(fs.readFileSync(previous));
const img2 = PNG.sync.read(fs.readFileSync(current));
const { width, height } = img1;
const diff = new PNG({ width, height });
const numDiffPixels = pixelmatch(
img1.data,
img2.data,
diff.data,
width,
height,
{ threshold: 0.1 }
);
const diffPercentage = (numDiffPixels / (width * height)) * 100;
return {
diffPercentage,
diffImage: diff,
hasMajorChanges: diffPercentage > 5 // Alert if >5% changed
};
}
⚠️ Tip: Set your threshold carefully. Small changes (like timestamps or ads) might cause false positives. A 5% threshold works well for most sites.
Setting Up Alerts
Slack Webhook Alert
async function sendSlackAlert(page, diffPercentage, screenshotUrl) {
const webhookUrl = process.env.SLACK_WEBHOOK_URL;
await fetch(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: `🚨 Visual change detected!`,
attachments: [{
color: 'danger',
fields: [
{ title: 'Page', value: page.name, short: true },
{ title: 'Change', value: `${diffPercentage.toFixed(2)}%`, short: true },
{ title: 'URL', value: page.url }
],
image_url: screenshotUrl
}]
})
});
}
GitHub Actions Scheduler
# .github/workflows/visual-monitor.yml
name: Visual Monitoring
on:
schedule:
- cron: '*/15 * * * *' # Every 15 minutes
workflow_dispatch:
jobs:
monitor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Run visual monitoring
env:
SNAPAPI_KEY: ${{ secrets.SNAPAPI_KEY }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: node monitor.js
Best Practices
- Monitor critical pages first - Homepage, login, checkout, pricing
- Include mobile views - Mobile bugs are common and often missed
- Set reasonable thresholds - Avoid alert fatigue from false positives
- Keep historical screenshots - Useful for debugging and tracking changes
- Run frequently - Every 15 minutes is a good balance
✅ Result: With this setup, you'll catch visual issues within minutes of deployment - before users notice!
Start Monitoring Your Site
Get 100 free screenshots per month - enough for basic monitoring of 3-4 pages.
Get Your API Key →