{"id":190,"date":"2025-10-08T20:05:03","date_gmt":"2025-10-09T00:05:03","guid":{"rendered":"https:\/\/scootercam.net\/notes\/?p=190"},"modified":"2025-10-08T20:05:38","modified_gmt":"2025-10-09T00:05:38","slug":"qr-codes","status":"publish","type":"post","link":"https:\/\/scootercam.net\/blog\/qr-codes\/","title":{"rendered":"QR Codes"},"content":{"rendered":"\n<p><em>Claude AI developed a cookie-based qr code tracker.<\/em><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Site-Wide Tracking System &#8211; Installation Guide<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udce6 What You Have<\/h2>\n\n\n\n<p>Three PHP files for comprehensive visitor tracking:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>track.php<\/strong> &#8211; Site-wide visitor tracking (include on every page)<\/li>\n\n\n\n<li><strong>qr.php<\/strong> &#8211; QR code redirect with enhanced tracking<\/li>\n\n\n\n<li><strong>qr-admin.php<\/strong> &#8211; Analytics dashboard with 5 views<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\ude80 Installation Steps<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Upload Files<\/h3>\n\n\n\n<p>Upload all three PHP files to your scootercam.net web root:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/public_html\/track.php\n\/public_html\/qr.php\n\/public_html\/qr-admin.php\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Set Directory Permissions<\/h3>\n\n\n\n<p>Make sure the directory is writable so SQLite can create the database:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>chmod 755 \/public_html\/\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Add Tracking to Every Page<\/h3>\n\n\n\n<p>Add this line at the <strong>very top<\/strong> of every PHP page you want to track:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php require_once 'track.php'; ?&gt;\n&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n...\n<\/code><\/pre>\n\n\n\n<p><strong>For non-PHP pages (HTML)<\/strong>, you have two options:<\/p>\n\n\n\n<p><strong>Option A:<\/strong> Rename <code>.html<\/code> files to <code>.php<\/code> and add the tracking line<\/p>\n\n\n\n<p><strong>Option B:<\/strong> Use <code>.htaccess<\/code> to parse HTML as PHP:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>AddType application\/x-httpd-php .html\n<\/code><\/pre>\n\n\n\n<p>Then add <code>&lt;?php require_once 'track.php'; ?&gt;<\/code> to your HTML files.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Change Admin Password<\/h3>\n\n\n\n<p>Edit <strong>qr-admin.php<\/strong> line 12:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>define('ADMIN_PASSWORD', 'your_secure_password_here');\n<\/code><\/pre>\n\n\n\n<p>Change <code>your_secure_password_here<\/code> to something secure.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Test the System<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Visit any page<\/strong> on your site \u2192 sets visitor cookie<\/li>\n\n\n\n<li><strong>Visit qr-admin.php<\/strong> \u2192 login with your password<\/li>\n\n\n\n<li><strong>Check &#8220;Overview&#8221; tab<\/strong> \u2192 should show 1 visitor, 1 page view<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: Create Your First QR Code<\/h3>\n\n\n\n<p>Generate a QR code pointing to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;scootercam.net\/qr.php?code=TEST&amp;dest=https:\/\/scootercam.net\/\n<\/code><\/pre>\n\n\n\n<p>Scan it with your phone and watch it appear in the admin!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udcca What Gets Tracked<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Site-Wide Tracking (track.php)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2705 Every page visit<\/li>\n\n\n\n<li>\u2705 Visitor cookie (1-year persistence)<\/li>\n\n\n\n<li>\u2705 First visit timestamp<\/li>\n\n\n\n<li>\u2705 Last visit timestamp<\/li>\n\n\n\n<li>\u2705 Total page views per visitor<\/li>\n\n\n\n<li>\u2705 Referrer information<\/li>\n\n\n\n<li>\u2705 User agent (device\/browser)<\/li>\n\n\n\n<li>\u2705 IP address<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">QR Code Tracking (qr.php)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2705 Which QR code was scanned<\/li>\n\n\n\n<li>\u2705 When it was scanned<\/li>\n\n\n\n<li>\u2705 Whether visitor is new or returning<\/li>\n\n\n\n<li>\u2705 Destination URL<\/li>\n\n\n\n<li>\u2705 Links visitor to their site browsing history<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Combined Intelligence<\/h3>\n\n\n\n<p>The system now knows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Did someone browse your site BEFORE scanning a QR?<\/li>\n\n\n\n<li>Did someone scan a QR THEN browse your site?<\/li>\n\n\n\n<li>How many visitors came from QR vs organic traffic?<\/li>\n\n\n\n<li>Full visitor journey from first touch to last activity<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udcf1 Admin Dashboard Views<\/h2>\n\n\n\n<p><strong>1. Overview<\/strong> &#8211; High-level stats<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Total visitors<\/li>\n\n\n\n<li>Page views<\/li>\n\n\n\n<li>QR scans<\/li>\n\n\n\n<li>Conversion rates<\/li>\n\n\n\n<li>Visitor source breakdown (QR only \/ Site only \/ Both)<\/li>\n<\/ul>\n\n\n\n<p><strong>2. Visitor Journeys<\/strong> &#8211; Track individual visitors<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Entry point (QR code or page URL)<\/li>\n\n\n\n<li>First and last seen timestamps<\/li>\n\n\n\n<li>Total page views<\/li>\n\n\n\n<li>Total QR scans<\/li>\n\n\n\n<li>Visitor type badge<\/li>\n<\/ul>\n\n\n\n<p><strong>3. QR Codes<\/strong> &#8211; QR performance metrics<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Total scans per code<\/li>\n\n\n\n<li>Unique visitors per code<\/li>\n\n\n\n<li>Returning scan counts<\/li>\n\n\n\n<li>Last scan timestamp<\/li>\n<\/ul>\n\n\n\n<p><strong>4. Page Views<\/strong> &#8211; Popular pages<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Most viewed pages<\/li>\n\n\n\n<li>Unique visitors per page<\/li>\n\n\n\n<li>Average views per visitor<\/li>\n<\/ul>\n\n\n\n<p><strong>5. Recent Activity<\/strong> &#8211; Real-time feed<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Last 50 actions (QR scans + page views)<\/li>\n\n\n\n<li>Timestamp<\/li>\n\n\n\n<li>Visitor ID<\/li>\n\n\n\n<li>Device info<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd27 Configuration Options<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">In track.php (line 9):<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>define('TRACK_PAGEVIEWS', true);\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>true<\/code> = Log every page view (recommended for low traffic)<\/li>\n\n\n\n<li><code>false<\/code> = Only set cookie, don&#8217;t log pages (lighter database)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">In qr.php (line 11):<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>define('ALLOWED_DOMAINS', &#91;'scootercam.net', 'www.scootercam.net']);\n<\/code><\/pre>\n\n\n\n<p>Add any additional domains you want to allow as QR destinations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\uddc4\ufe0f Database Structure<\/h2>\n\n\n\n<p>The system creates three tables automatically:<\/p>\n\n\n\n<p><strong>visitors<\/strong> &#8211; One row per unique visitor<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Aggregated stats (total pageviews, total QR scans)<\/li>\n\n\n\n<li>First and last seen timestamps<\/li>\n\n\n\n<li>First QR scan timestamp<\/li>\n<\/ul>\n\n\n\n<p><strong>page_views<\/strong> &#8211; One row per page view<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Full page URL<\/li>\n\n\n\n<li>Timestamp<\/li>\n\n\n\n<li>Referrer<\/li>\n\n\n\n<li>Device info<\/li>\n<\/ul>\n\n\n\n<p><strong>qr_scans<\/strong> &#8211; One row per QR scan<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>QR code identifier<\/li>\n\n\n\n<li>Destination URL<\/li>\n\n\n\n<li>New vs returning status<\/li>\n\n\n\n<li>Timestamp<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd12 Security Features<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2705 SQLite prepared statements (injection-proof)<\/li>\n\n\n\n<li>\u2705 Password-protected admin panel<\/li>\n\n\n\n<li>\u2705 HTTP-only, secure cookies<\/li>\n\n\n\n<li>\u2705 Domain whitelist for QR redirects<\/li>\n\n\n\n<li>\u2705 Admin\/tracking scripts excluded from logs<\/li>\n\n\n\n<li>\u2705 Silent failure (tracking errors don&#8217;t break pages)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83c\udfaf Usage Example<\/h2>\n\n\n\n<p><strong>Scenario:<\/strong> Event poster with QR code<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Print poster with QR code pointing to: <code>https:\/\/scootercam.net\/qr.php?code=POSTER_DOWNTOWN&amp;dest=https:\/\/scootercam.net\/events<\/code><\/li>\n\n\n\n<li>Someone scans it with their phone<\/li>\n\n\n\n<li>System logs: &#8220;New visitor scanned POSTER_DOWNTOWN at 2pm&#8221;<\/li>\n\n\n\n<li>They browse to <code>\/gallery<\/code> and <code>\/contact<\/code><\/li>\n\n\n\n<li>System logs: &#8220;Same visitor viewed 2 more pages&#8221;<\/li>\n\n\n\n<li>Three days later, they scan ANOTHER QR code<\/li>\n\n\n\n<li>System logs: &#8220;Returning visitor scanned STICKER_CITY at 5pm&#8221;<\/li>\n<\/ol>\n\n\n\n<p><strong>In admin, you see:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>This visitor&#8217;s complete journey<\/li>\n\n\n\n<li>Both QR codes they scanned<\/li>\n\n\n\n<li>All pages they viewed<\/li>\n\n\n\n<li>Total engagement time span<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udcde Troubleshooting<\/h2>\n\n\n\n<p><strong>Database not creating?<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Check directory write permissions<\/li>\n\n\n\n<li>Look for PHP errors: <code>tail -f \/var\/log\/apache2\/error.log<\/code><\/li>\n<\/ul>\n\n\n\n<p><strong>Page views not showing?<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Make sure <code>track.php<\/code> is included BEFORE any HTML output<\/li>\n\n\n\n<li>Check that <code>TRACK_PAGEVIEWS<\/code> is <code>true<\/code><\/li>\n<\/ul>\n\n\n\n<p><strong>QR scans work but page views don&#8217;t?<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Verify <code>track.php<\/code> is included on those pages<\/li>\n\n\n\n<li>Check that pages are parsed as PHP (not static HTML)<\/li>\n<\/ul>\n\n\n\n<p><strong>Admin shows 0 visitors?<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Try a longer time range (90 days)<\/li>\n\n\n\n<li>Check that database file exists: <code>ls -la qr_tracking.db<\/code><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\ude80 Next Steps<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Add tracking to all your pages<\/li>\n\n\n\n<li>Create QR codes for different campaigns<\/li>\n\n\n\n<li>Monitor visitor behavior patterns<\/li>\n\n\n\n<li>Identify which QR codes drive the most engagement<\/li>\n\n\n\n<li>See which pages visitors love (or leave quickly)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>Remember:<\/strong> Change the admin password before going live!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Claude AI developed a cookie-based qr code tracker. Site-Wide Tracking System &#8211; Installation Guide \ud83d\udce6 What You Have Three PHP files for comprehensive visitor tracking: \ud83d\ude80 Installation Steps Step 1: Upload Files Upload all three PHP files to your scootercam.net web root: Step 2: Set Directory Permissions Make sure the directory is writable so SQLite &#8230; <a title=\"QR Codes\" class=\"read-more\" href=\"https:\/\/scootercam.net\/blog\/qr-codes\/\" aria-label=\"Read more about QR Codes\">Read more<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[24],"tags":[],"class_list":["post-190","post","type-post","status-publish","format-standard","hentry","category-guides"],"_links":{"self":[{"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/posts\/190","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/comments?post=190"}],"version-history":[{"count":2,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/posts\/190\/revisions"}],"predecessor-version":[{"id":192,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/posts\/190\/revisions\/192"}],"wp:attachment":[{"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/media?parent=190"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/categories?post=190"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/tags?post=190"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}