add url generator

This commit is contained in:
chris 2025-10-04 18:52:18 -04:00
parent c02e7fb4b6
commit a0a184236c

257
url/index.html Normal file
View File

@ -0,0 +1,257 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Plausible Link & QR Code Generator</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/qr-code-styling@1.5.0/lib/qr-code-styling.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
}
</style>
</head>
<body class="bg-slate-100 flex items-center justify-center min-h-screen p-4">
<div class="bg-white p-8 rounded-2xl shadow-lg max-w-2xl w-full">
<!-- Header -->
<div class="text-center mb-8">
<h1 class="text-3xl font-bold text-slate-800">Marketing Link & QR Code Generator</h1>
<p class="text-slate-500 mt-2">Create special links for your business cards and flyers to see how many visitors they bring to our website!</p>
</div>
<!-- Form -->
<form id="link-form" class="space-y-6">
<div>
<label for="base-url" class="block text-sm font-medium text-slate-700 mb-1">Our Website URL</label>
<input type="text" id="base-url" value="https://beachpartyballoons.com" class="block w-full px-3 py-2 bg-slate-50 border border-slate-300 rounded-md shadow-sm placeholder-slate-400 focus:outline-none focus:ring-blue-500 focus:border-blue-500" readonly>
<p class="text-xs text-slate-400 mt-1">This is locked to our main website.</p>
</div>
<div>
<label for="campaign" class="block text-sm font-medium text-slate-700 mb-1">What is this link for?</label>
<input type="text" id="campaign" placeholder="e.g., Business Card, Holiday Flyer, Craft Fair Poster" required class="block w-full px-3 py-2 bg-white border border-slate-300 rounded-md shadow-sm placeholder-slate-400 focus:outline-none focus:ring-blue-500 focus:border-blue-500">
<p class="text-xs text-slate-400 mt-1">This helps us group our marketing efforts.</p>
</div>
<div>
<label for="source" class="block text-sm font-medium text-slate-700 mb-1">Where will you put this link/QR code?</label>
<input type="text" id="source" placeholder="e.g., Milford Office Flyer, Wedding Expo Handout" required class="block w-full px-3 py-2 bg-white border border-slate-300 rounded-md shadow-sm placeholder-slate-400 focus:outline-none focus:ring-blue-500 focus:border-blue-500">
<p class="text-xs text-slate-400 mt-1">Be specific so we know exactly what worked!</p>
</div>
<div>
<label for="employee-name" class="block text-sm font-medium text-slate-700 mb-1">Your Name (Optional, for Business Cards)</label>
<input type="text" id="employee-name" placeholder="e.g., Jane Doe" class="block w-full px-3 py-2 bg-white border border-slate-300 rounded-md shadow-sm placeholder-slate-400 focus:outline-none focus:ring-blue-500 focus:border-blue-500">
<p class="text-xs text-slate-400 mt-1">This lets us see who's driving the most traffic!</p>
</div>
<!-- New Customization Section -->
<div>
<label class="block text-sm font-medium text-slate-700 mb-2">QR Code Style (Optional)</label>
<div class="p-4 border rounded-lg bg-slate-50 space-y-4">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label for="dots-style" class="block text-xs font-medium text-slate-600 mb-1">Dot Style</label>
<select id="dots-style" class="block w-full px-3 py-2 bg-white border border-slate-300 rounded-md shadow-sm">
<option value="square">Square</option>
<option value="dots">Dots</option>
<option value="rounded">Rounded</option>
<option value="extra-rounded">Extra Rounded</option>
<option value="classy">Classy</option>
<option value="classy-rounded">Classy Rounded</option>
</select>
</div>
<div>
<label for="color-dots" class="block text-xs font-medium text-slate-600 mb-1">Dot Color</label>
<input type="color" id="color-dots" value="#00A99D" class="w-full h-10 p-1 bg-white border border-slate-300 rounded-md cursor-pointer">
</div>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 pt-4 border-t">
<div>
<label for="corner-square-style" class="block text-xs font-medium text-slate-600 mb-1">Corner Square Style</label>
<select id="corner-square-style" class="block w-full px-3 py-2 bg-white border border-slate-300 rounded-md shadow-sm">
<option value="square">Square</option>
<option value="dot">Dot</option>
<option value="extra-rounded">Extra Rounded</option>
</select>
</div>
<div>
<label for="color-corner-square" class="block text-xs font-medium text-slate-600 mb-1">Corner Square Color</label>
<input type="color" id="color-corner-square" value="#009FDD" class="w-full h-10 p-1 bg-white border border-slate-300 rounded-md cursor-pointer">
</div>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label for="corner-dot-style" class="block text-xs font-medium text-slate-600 mb-1">Inner Corner Style</label>
<select id="corner-dot-style" class="block w-full px-3 py-2 bg-white border border-slate-300 rounded-md shadow-sm">
<option value="square">Square</option>
<option value="dot">Dot</option>
</select>
</div>
<div>
<label for="color-corner-dot" class="block text-xs font-medium text-slate-600 mb-1">Inner Corner Color</label>
<input type="color" id="color-corner-dot" value="#98C73D" class="w-full h-10 p-1 bg-white border border-slate-300 rounded-md cursor-pointer">
</div>
</div>
<div class="pt-4 border-t">
<label for="color-light" class="block text-xs font-medium text-slate-600 mb-1">Background Color</label>
<input type="color" id="color-light" value="#ffffff" class="w-full h-10 p-1 bg-white border border-slate-300 rounded-md cursor-pointer">
</div>
</div>
<p class="text-xs text-slate-400 mt-2"><strong>Tip:</strong> Keep a high contrast between the code and background for best scanning results.</p>
</div>
<button type="submit" class="w-full bg-blue-600 text-white font-bold py-3 px-4 rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-300">
Generate Link & QR Code
</button>
</form>
<!-- Output Section -->
<div id="output-section" class="mt-8 pt-6 border-t border-slate-200 hidden">
<h2 class="text-2xl font-bold text-slate-800 text-center mb-6">Your Marketing Assets are Ready!</h2>
<div class="grid md:grid-cols-2 gap-8 items-center">
<!-- Left Side: Link Info -->
<div class="space-y-4">
<div>
<h3 class="font-semibold text-slate-700 mb-2">1. Your Trackable Link</h3>
<div class="flex items-center space-x-2">
<input id="generated-link" type="text" class="w-full px-3 py-2 bg-slate-100 border border-slate-300 rounded-md text-sm" readonly>
<button id="copy-button" class="bg-slate-200 hover:bg-slate-300 text-slate-700 font-medium py-2 px-4 rounded-md transition-colors">Copy</button>
</div>
</div>
<div>
<h3 class="font-semibold text-slate-700 mb-2">2. Download Your QR Code</h3>
<p class="text-sm text-slate-500 mb-3">Add this image to your flyer or business card. When someone scans it, we can track their visit.</p>
<button id="download-button" class="w-full text-center bg-green-600 text-white font-bold py-2 px-4 rounded-lg hover:bg-green-700 transition-colors">Download QR Code (.png)</button>
</div>
</div>
<!-- Right Side: QR Code Image -->
<div class="flex justify-center items-center p-4 bg-slate-50 rounded-lg border">
<div id="qrcode-container"></div>
</div>
</div>
</div>
<!-- Footer -->
<div class="text-center mt-8">
<p class="text-sm text-slate-500"><strong>Why do we do this?</strong> These special links help us understand which of our marketing ideas are the most effective at bringing new customers to our website. Thanks for helping out!</p>
</div>
</div>
<script>
const form = document.getElementById('link-form');
const outputSection = document.getElementById('output-section');
const generatedLinkInput = document.getElementById('generated-link');
const qrcodeContainer = document.getElementById('qrcode-container');
const copyButton = document.getElementById('copy-button');
const downloadButton = document.getElementById('download-button');
let qrCodeInstance = null;
// Helper function to format text for URLs (e.g., "Business Card" -> "business_card")
const slugify = (text) => text.toString().toLowerCase().trim()
.replace(/\s+/g, '_') // Replace spaces with _
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
.replace(/\-\-+/g, '_'); // Replace multiple - with single _
form.addEventListener('submit', (e) => {
e.preventDefault();
const baseURL = document.getElementById('base-url').value;
const campaign = document.getElementById('campaign').value;
const source = document.getElementById('source').value;
const employeeName = document.getElementById('employee-name').value;
// Get new style values
const dotsStyle = document.getElementById('dots-style').value;
const cornerSquareStyle = document.getElementById('corner-square-style').value;
const cornerDotStyle = document.getElementById('corner-dot-style').value;
const colorDots = document.getElementById('color-dots').value;
const colorCornerSquare = document.getElementById('color-corner-square').value;
const colorCornerDot = document.getElementById('color-corner-dot').value;
const colorLight = document.getElementById('color-light').value;
// Build the URL with UTM parameters
const url = new URL(baseURL);
url.searchParams.set('utm_campaign', slugify(campaign));
url.searchParams.set('utm_source', slugify(source));
url.searchParams.set('utm_medium', 'print'); // Hardcoded as this tool is for physical media
if (employeeName) {
url.searchParams.set('utm_content', slugify(employeeName));
}
const finalURL = url.toString();
generatedLinkInput.value = finalURL;
const qrOptions = {
width: 200,
height: 200,
type: 'svg',
data: finalURL,
dotsOptions: {
color: colorDots,
type: dotsStyle
},
backgroundOptions: {
color: colorLight,
},
cornersSquareOptions: {
color: colorCornerSquare,
type: cornerSquareStyle
},
cornersDotOptions: {
color: colorCornerDot,
type: cornerDotStyle
}
};
if (qrCodeInstance) {
qrCodeInstance.update(qrOptions);
} else {
qrCodeInstance = new QRCodeStyling(qrOptions);
qrcodeContainer.innerHTML = '';
qrCodeInstance.append(qrcodeContainer);
}
outputSection.classList.remove('hidden');
});
downloadButton.addEventListener('click', () => {
if (!qrCodeInstance) return;
const campaign = document.getElementById('campaign').value;
const source = document.getElementById('source').value;
const downloadFileName = `qr_${slugify(campaign)}_${slugify(source)}`;
qrCodeInstance.download({ name: downloadFileName, extension: "png" });
});
copyButton.addEventListener('click', () => {
generatedLinkInput.select();
try {
// Use the newer clipboard API if available
navigator.clipboard.writeText(generatedLinkInput.value);
copyButton.textContent = 'Copied!';
setTimeout(() => { copyButton.textContent = 'Copy'; }, 2000);
} catch (err) {
// Fallback for older browsers
document.execCommand('copy');
copyButton.textContent = 'Copied!';
setTimeout(() => { copyButton.textContent = 'Copy'; }, 2000);
}
});
</script>
</body>
</html>