Appearance
Dynamic QR Codes Guide
Create QR codes with editable destination URLs and scan tracking.
What Are Dynamic QR Codes?
Dynamic QR codes point to a short URL that redirects to your target URL. Unlike static QR codes, you can change where they point without reprinting.
Static QR Code:
QR → https://restaurant.com/menu-2024.pdfIf you update the menu, you need new QR codes.
Dynamic QR Code:
QR → https://www.qrcodeapi.io/r/abc123 → https://restaurant.com/menu.pdfUpdate the destination anytime—the QR code stays the same.
Creating Dynamic QR Codes
Step 1: Create a Dynamic Link
bash
curl -X POST "https://www.qrcodeapi.io/api/links" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Restaurant Menu",
"targetUrl": "https://restaurant.com/menu.pdf"
}'Response:
json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Restaurant Menu",
"shortCode": "abc123",
"targetUrl": "https://restaurant.com/menu.pdf",
"scanCount": 0,
"createdAt": "2024-01-15T10:30:00Z"
}Step 2: Generate the QR Code
bash
curl "https://www.qrcodeapi.io/api/generate" \
-H "Authorization: Bearer YOUR_API_KEY" \
-G \
--data-urlencode "data=https://www.qrcodeapi.io/r/abc123" \
--data "size=500" \
-o menu-qr.pngStep 3: Update When Needed
bash
curl -X PUT "https://www.qrcodeapi.io/api/links?id=550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"targetUrl": "https://restaurant.com/summer-menu.pdf"
}'The same QR code now points to the summer menu!
Complete JavaScript Example
javascript
const API_KEY = process.env.QRCODE_API_KEY;
class DynamicQR {
// Create a dynamic link
async createLink(name, targetUrl) {
const response = await fetch('https://www.qrcodeapi.io/api/links', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ name, targetUrl })
});
if (!response.ok) {
throw new Error((await response.json()).message);
}
return response.json();
}
// Generate QR code for a link
async generateQR(shortCode, options = {}) {
const params = new URLSearchParams({
data: `https://www.qrcodeapi.io/r/${shortCode}`,
size: options.size || 300,
color: options.color || '000000',
background: options.background || 'ffffff'
});
const response = await fetch(
`https://www.qrcodeapi.io/api/generate?${params}`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
);
if (!response.ok) {
throw new Error((await response.json()).message);
}
return response.blob();
}
// Update a link's target URL
async updateLink(linkId, updates) {
const response = await fetch(
`https://www.qrcodeapi.io/api/links?id=${linkId}`,
{
method: 'PUT',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(updates)
}
);
if (!response.ok) {
throw new Error((await response.json()).message);
}
return response.json();
}
// Get analytics for a link
async getAnalytics(linkId) {
const response = await fetch(
`https://www.qrcodeapi.io/api/analytics?linkId=${linkId}`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
);
if (!response.ok) {
throw new Error((await response.json()).message);
}
return response.json();
}
// Full workflow: create link + generate QR
async create(name, targetUrl, qrOptions = {}) {
const link = await this.createLink(name, targetUrl);
const qrBlob = await this.generateQR(link.shortCode, qrOptions);
return {
link,
qrBlob,
shortUrl: `https://www.qrcodeapi.io/r/${link.shortCode}`
};
}
}
// Usage
const dynamicQR = new DynamicQR();
// Create a dynamic QR code
const { link, qrBlob, shortUrl } = await dynamicQR.create(
'Product Launch',
'https://company.com/launch',
{ size: 500, color: '4f46e5' }
);
console.log(`Short URL: ${shortUrl}`);
console.log(`Link ID: ${link.id}`);
// Later: update the destination
await dynamicQR.updateLink(link.id, {
targetUrl: 'https://company.com/launch-v2'
});
// Check analytics
const analytics = await dynamicQR.getAnalytics(link.id);
console.log(`Total scans: ${analytics.analytics.totalScans}`);Use Cases
Restaurant Menus
javascript
// Create menu QR codes for each table
const tables = [1, 2, 3, 4, 5];
for (const table of tables) {
const { link } = await dynamicQR.create(
`Table ${table} Menu`,
'https://restaurant.com/menu',
{ size: 300 }
);
console.log(`Table ${table}: ${link.shortCode}`);
}
// Update all menus to seasonal menu
for (const linkId of menuLinkIds) {
await dynamicQR.updateLink(linkId, {
targetUrl: 'https://restaurant.com/winter-menu'
});
}Marketing Campaigns
javascript
// A/B test landing pages
const campaign = await dynamicQR.create(
'Summer Sale',
'https://shop.com/sale-a', // Start with variant A
{ size: 500, color: '22c55e' }
);
// Print and distribute the QR codes...
// After 1 week, switch to variant B
await dynamicQR.updateLink(campaign.link.id, {
targetUrl: 'https://shop.com/sale-b'
});
// Compare analytics
const analytics = await dynamicQR.getAnalytics(campaign.link.id);Event Materials
javascript
// Event schedule QR code
const event = await dynamicQR.create(
'Conference 2024',
'https://conference.com/schedule',
{ size: 400 }
);
// Update in real-time during the event
await dynamicQR.updateLink(event.link.id, {
targetUrl: 'https://conference.com/schedule?room=changed'
});Product Packaging
javascript
// Product info QR code
const product = await dynamicQR.create(
'Widget Pro',
'https://company.com/products/widget-pro',
{ size: 200, errorCorrection: 'H' }
);
// Update when product page changes
await dynamicQR.updateLink(product.link.id, {
targetUrl: 'https://company.com/products/widget-pro-v2'
});
// Redirect discontinued products
await dynamicQR.updateLink(oldProductId, {
targetUrl: 'https://company.com/products/widget-pro-replacement'
});Analytics
Track every scan with detailed analytics:
javascript
const analytics = await dynamicQR.getAnalytics(linkId);
// Total scans
console.log(`Total: ${analytics.analytics.totalScans}`);
console.log(`Unique: ${analytics.analytics.uniqueScans}`);
// Scans by day
for (const day of analytics.analytics.scansByDay) {
console.log(`${day.date}: ${day.scans} scans`);
}
// Top countries
for (const country of analytics.analytics.scansByCountry.slice(0, 5)) {
console.log(`${country.country}: ${country.scans} scans`);
}
// Device breakdown
for (const device of analytics.analytics.scansByDevice) {
console.log(`${device.device}: ${device.scans} scans`);
}Limits by Plan
| Plan | Dynamic Links | Analytics Retention |
|---|---|---|
| Free | 5 | 30 days |
| Starter | 50 | 90 days |
| Pro | 500 | 1 year |
| Enterprise | Unlimited | Unlimited |
Best Practices
1. Descriptive Names
Use clear, descriptive names for your links:
- ✅ "Summer 2024 Menu - Downtown Location"
- ❌ "menu1"
2. Organize by Category
Group related links by naming convention:
- "Campaign: Summer Sale"
- "Campaign: Black Friday"
- "Product: Widget Pro"
3. Regular Maintenance
- Review analytics monthly
- Delete unused links
- Update broken target URLs
4. Test Before Print
Always test scan the QR code before printing:
- Verify it redirects correctly
- Test on multiple devices
- Check from various distances
5. Keep Target URLs Live
Never delete or change URL structure of target pages without updating the dynamic link first.
Related
- Dynamic Links API - Full API reference
- Analytics API - Analytics endpoints
- Track QR Scans - Step-by-step tracking guide