PageSourceSearch

https://snapglyph.com/news/

html snapglyph.com collected 2026-10-02 00:55:51 UTC 36,168 bytes, 348 lines download raw bytes

1<!DOCTYPE html><html lang="en"><head>
1<script>
2        window.dataLayer = window.dataLayer || [];
3        function gtag(){dataLayer.push(arguments);}
4        gtag('consent', 'default', {
5          'ad_storage': 'denied',
6          'ad_user_data': 'denied',
7          'ad_personalization': 'denied',
8          'analytics_storage': 'denied'
9        });
10      </script>
10<script>
vendor: 368 bytes, lines 10-15
10
11        (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
12        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
13        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
14        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
15        })(window,document,'script','dataLayer','
15GTM-MHBLQSM9
vendor: 10 bytes, lines 15-16
15');
16      
16</script>
16<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="description" content="Product launches, company milestones, partnerships, and press releases from SnapGlyph."><title>Newsroom - SnapGlyph</title><link rel="canonical" href="https://snapglyph.com/news/"><!-- Hreflang tags for international targeting --><link rel="alternate" hreflang="en-US" href="https://snapglyph.com/news/"><link rel="alternate" hreflang="en-CA" href="https://snapglyph.com/news/"><link rel="alternate" hreflang="en-GB" href="https://snapglyph.com/news/"><link rel="alternate" hreflang="x-default" href="https://snapglyph.com/news/"><!-- Open Graph meta tags --><meta property="og:title" content="Newsroom - SnapGlyph"><meta property="og:description" content="Product launches, company milestones, partnerships, and press releases from SnapGlyph."><meta property="og:url" content="https://snapglyph.com/news/"><meta property="og:site_name" content="SnapGlyph"><meta property="og:type" content="website"><meta property="og:locale" content="en_US"><!-- Twitter Card meta tags --><meta name="twitter:card" content="summary_large_image"><meta name="twitter:site" content="@snapglyph"><meta name="twitter:title" content="Newsroom - SnapGlyph"><meta name="twitter:description" content="Product launches, company milestones, partnerships, and press releases from SnapGlyph."><link rel="alternate" type="application/rss+xml" title="SnapGlyph Newsroom" href="/news/rss.xml"><link rel="stylesheet" href="/styles.css"><!-- Favicons --><link rel="icon" href="/favicon.ico" sizes="32x32"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="manifest" href="/site.webmanifest"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@600;700;800&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"><!-- Structured Data -->
16<script type="application/ld+json">{"@context":"https://schema.org","@type":"Organization","name":"SnapGlyph","url":"https://snapglyph.com","logo":"https://snapglyph.com/logo.png","description":"QR codes, branded short links, and link-in-bio pages. One platform for every link you share.","sameAs":["https://twitter.com/snapglyph","https://linkedin.com/company/snapglyph"]}</script>
16<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebSite","name":"SnapGlyph","url":"https://snapglyph.com","description":"QR Codes, Short Links & Link-in-Bio — Link Management Platform"}</script>
16<script type="application/ld+json">{"@context":"https://schema.org","@type":"CollectionPage","name":"SnapGlyph Newsroom","description":"Product launches, company milestones, partnerships, and press releases from SnapGlyph.","url":"https://snapglyph.com/news","mainEntity":{"@type":"ItemList","itemListElement":[{"@type":"ListItem","position":1,"url":"https://snapglyph.com/news/snapglyph-launches-on-product-hunt","name":"SnapGlyph Launches on Product Hunt"},{"@type":"ListItem","position":2,"url":"https://snapglyph.com/news/snapglyph-releases-mcp-server","name":"SnapGlyph Releases SnapGlyph MCP Server"},{"@type":"ListItem","position":3,"url":"https://snapglyph.com/news/snapglyph-introduces-parameter-management","name":"SnapGlyph Introduces Link Tracking Parameter Management"},{"@type":"ListItem","position":4,"url":"https://snapglyph.com/news/snapglyph-releases-smart-qr-codes-and-smart-shortlinks","name":"SnapGlyph Releases Smart QR Codes and Smart Shortlinks"}]}}</script>
16<script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://snapglyph.com"},{"@type":"ListItem","position":2,"name":"Newsroom","item":"https://snapglyph.com/news"}]}</script>
16</head><body>
vendor: 67 bytes, line 16
16<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
16GTM-MHBLQSM9
vendor: 82 bytes, line 16
16" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
16<nav class="nav"><div class="nav-container"><a href="/" class="nav-logo"><img src="/_astro/logo.C49gomSg_gExLD.svg" alt="SnapGlyph" loading="lazy" decoding="async" width="100" height="10"></a><div class="nav-links"><div class="nav-dropdown"><button class="nav-dropdown-toggle" aria-expanded="false" aria-haspopup="true">Features<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 5l3 3 3-3"></path></svg></button><div class="nav-dropdown-menu"><a href="/features/qr-codes/">QR Code Generator</a><a href="/features/url-shortener/">Link Shortener</a><a href="/features/link-in-bio/">Link in Bio</a><a href="/features/snapglyph-mcp/">SnapGlyph MCP</a></div></div><a href="/pricing/">Pricing</a><div class="nav-dropdown nav-resources-dropdown"><button class="nav-dropdown-toggle" aria-expanded="false" aria-haspopup="true">Resources<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 5l3 3 3-3"></path></svg></button><div class="nav-dropdown-menu nav-mega-menu"><div class="nav-mega-col"><span class="nav-mega-heading">Use Cases</span><a href="/use-cases/business-owners/"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="12" height="10" rx="1.5"></rect><line x1="5" y1="6" x2="8" y2="6"></line><line x1="5" y1="8.5" x2="7" y2="8.5"></line><rect x="9.5" y="6" width="3" height="3" rx="0.5"></rect></svg>For Business</a><a href="/use-cases/restaurants/"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 2v5a2 2 0 002 2h0a2 2 0 002-2V2"></path><line x1="6" y1="9" x2="6" y2="14"></line><line x1="12" y1="2" x2="12" y2="6"></line><path d="M10 2v3a2 2 0 002 2h0V14"></path></svg>For Restaurants</a></div><div class="nav-mega-divider"></div><div class="nav-mega-col"><span class="nav-mega-heading">Learn</span><a href="/blog/"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 2.5h7a2 2 0 012 2V13a0.5 0.5 0 01-0.5 0.5H5a2 2 0 01-2-2V2.5z"></path><line x1="5.5" y1="5.5" x2="9.5" y2="5.5"></line><line x1="5.5" y1="8" x2="9.5" y2="8"></line><line x1="5.5" y1="10.5" x2="8" y2="10.5"></line></svg>Blog</a><a href="/compare/"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="3" x2="8" y2="13.5"></line><line x1="6" y1="13.5" x2="10" y2="13.5"></line><line x1="2.5" y1="5" x2="13.5" y2="5"></line><line x1="3.5" y1="5" x2="3.5" y2="8"></line><line x1="12.5" y1="5" x2="12.5" y2="8"></line><path d="M1.5 8 Q3.5 11 5.5 8"></path><path d="M10.5 8 Q12.5 11 14.5 8"></path></svg>Comparisons</a></div><div class="nav-mega-divider"></div><div class="nav-mega-col nav-mega-blog"><span class="nav-mega-heading">Latest from SnapGlyph</span><a href="/blog/practical-guide-to-using-qr-codes/" class="nav-mega-post"><img src="/_astro/practical-guide-cover.6-cUzm15_127Ebd.webp" alt loading="lazy" decoding="async" width="2064" height="512" class="nav-mega-post-img"><span class="nav-mega-post-title">A Practical Guide to Using QR Codes</span></a><a href="/blog/" class="nav-mega-blog-link">View all articles &rarr;</a></div></div></div></div><div class="nav-auth"><a href="/support/" target="_blank" class="nav-support-link">Support</a><a href="https://app.snapglyph.com/auth/signin" class="nav-btn-secondary" data-track="signin_click" data-track-location="nav">Sign In</a><a href="https://app.snapglyph.com/auth/signup" class="nav-cta" data-track="cta_click" data-track-location="nav" data-track-text="Get Started">Get Started</a></div><button class="nav-mobile-toggle" aria-label="Toggle menu" aria-expanded="false"><svg class="nav-icon-menu" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg><svg class="nav-icon-close" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></button></div><div class="nav-mobile-menu"><div class="nav-mobile-links"><div class="nav-mobile-dropdown"><button class="nav-mobile-dropdown-toggle" aria-expanded="false">Features<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 5l3 3 3-3"></path></svg></button><div class="nav-mobile-dropdown-menu"><a href="/features/qr-codes/">QR Code Generator</a><a href="/features/url-shortener/">Link Shortener</a><a href="/features/link-in-bio/">Link in Bio</a><a href="/features/snapglyph-mcp/">SnapGlyph MCP</a></div></div><a href="/pricing/">Pricing</a><div class="nav-mobile-dropdown nav-mobile-resources-dropdown"><button class="nav-mobile-dropdown-toggle" aria-expanded="false">Resources<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 5l3 3 3-3"></path></svg></button><div class="nav-mobile-dropdown-menu"><span class="nav-mobile-dropdown-heading">Use Cases</span><a href="/use-cases/business-owners/">For Business</a><a href="/use-cases/restaurants/">For Restaurants</a><span class="nav-mobile-dropdown-heading nav-mobile-dropdown-heading-spaced">Compare</span><a href="/compare/snapglyph-vs-linktree/">vs. Linktree</a><a href="/compare/snapglyph-vs-bitly/">vs. Bitly</a><a href="/compare/snapglyph-vs-beaconstac/">vs. Beaconstac</a><a href="/compare/snapglyph-vs-rebrandly/">vs. Rebrandly</a><a href="/compare/snapglyph-vs-beacons/">vs. Beacons</a><span class="nav-mobile-dropdown-heading nav-mobile-dropdown-heading-spaced">Blog</span><a href="/blog/">View all articles</a><span class="nav-mobile-dropdown-heading nav-mobile-dropdown-heading-spaced">
16Newsroom</span><a href="/news/">Latest news</a></div></div></div><div class="nav-mobile-auth"><a href="/support/" target="_blank" class="nav-support-link">Support</a><a href="https://app.snapglyph.com/auth/signin" class="nav-btn-secondary" data-track="signin_click" data-track-location="mobile_nav">Sign In</a><a href="https://app.snapglyph.com/auth/signup" class="nav-cta" data-track="cta_click" data-track-location="mobile_nav" data-track-text="Get Started">Get Started</a></div></div></nav><main class="newsroom-page"><div class="newsroom-container"><header class="newsroom-header"><span class="newsroom-eyebrow">Newsroom</span><h1>Latest from SnapGlyph</h1><p>Product launches, company milestones, and press from the team building SnapGlyph.</p><a href="/news/rss.xml" class="newsroom-rss-link" aria-label="Subscribe to the SnapGlyph newsroom RSS feed"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 11a9 9 0 0 1 9 9"></path><path d="M4 4a16 16 0 0 1 16 16"></path><circle cx="5" cy="19" r="1"></circle></svg>Subscribe via RSS</a></header><a class="newsroom-featured" href="https://www.producthunt.com/posts/snapglyph" data-category="product" target="_blank" rel="noopener noreferrer"><div class="newsroom-featured-media"><img src="/_astro/snapglyph-launches-on-product-hunt.DMeHxwyV_ZxzgdE.webp" alt="SnapGlyph Launches on Product Hunt - Image generated using AI." loading="eager" decoding="async" width="1200" height="675"></div><div class="newsroom-featured-body"><div class="newsroom-featured-meta"><span class="newsroom-tag" data-category="product">Product</span><span class="newsroom-dateline">CALGARY, AB</span><time datetime="2026-08-02T00:00:00.000Z">August 2, 2026</time></div><h2>SnapGlyph Launches on Product Hunt</h2><p>QR codes, branded short links, and Link Hubs in one tool — SnapGlyph is now live on Product Hunt.</p><span class="newsroom-featured-cta">Read on Product Hunt<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="13 6 19 12 13 18"></polyline></svg></span></div></a><div class="newsroom-secondary-grid"><a class="newsroom-card newsroom-card-compact" href="/news/snapglyph-releases-mcp-server/" data-category="product"><div class="newsroom-card-image"><img src="/_astro/snapglyph-releases-mcp-server.De4lpra8_ZzmRhx.webp" alt="SnapGlyph Releases SnapGlyph MCP Server - Image generated using AI." loading="lazy" decoding="async" width="1200" height="676"></div><div class="newsroom-card-body"><div class="newsroom-card-meta"><span class="newsroom-tag" data-category="product">Product</span><time datetime="2026-06-29T00:00:00.000Z">June 29, 2026</time></div><h3>SnapGlyph Releases SnapGlyph MCP Server</h3><p>QR code and tracked shortlink generation now happens inside the AI tools organizations and business operators already use — no app-switching required.</p></div></a><a class="newsroom-card newsroom-card-compact" href="/news/snapglyph-introduces-parameter-management/" data-category="product"><div class="newsroom-card-image"><img src="/_astro/snapglyph-introduces-parameter-management.DG4x9YBp_2oKvJe.webp" alt="SnapGlyph Introduces Link Tracking Parameter Management - Image generated using AI." loading="lazy" decoding="async" width="1200" height="676"></div><div class="newsroom-card-body"><div class="newsroom-card-meta"><span class="newsroom-tag" data-category="product">Product</span><time datetime="2026-06-19T00:00:00.000Z">June 19, 2026</time></div><h3>SnapGlyph Introduces Link Tracking Parameter Management</h3><p>New controls and governance for UTM tracking parameters keep tracking data consistent across teams — and make pre-set parameters one click to apply.</p></div></a></div><div class="newsroom-archive" data-active-category="all"><div class="newsroom-filters" role="tablist" aria-label="Filter news by category"><button type="button" class="newsroom-chip is-active" data-filter="all" role="tab" aria-selected="true">All</button><button type="button" class="newsroom-chip" data-filter="product" role="tab" aria-selected="false">Product</button><button type="button" class="newsroom-chip" data-filter="company" role="tab" aria-selected="false">Company</button><button type="button" class="newsroom-chip" data-filter="press-release" role="tab" aria-selected="false">Press</button><button type="button" class="newsroom-chip" data-filter="partnerships" role="tab" aria-selected="false">Partnerships</button><button type="button" class="newsroom-chip" data-filter="events" role="tab" aria-selected="false">Events</button><button type="button" class="newsroom-chip" data-filter="awards" role="tab" aria-selected="false">Awards</button></div><section class="newsroom-year-section"><div class="newsroom-year-divider"><span>2026</span><span class="newsroom-year-rule" aria-hidden="true"></span></div>
16<div class="newsroom-grid"><a class="newsroom-card" href="/news/snapglyph-releases-smart-qr-codes-and-smart-shortlinks/" data-category="product"><div class="newsroom-card-image"><img src="/_astro/snapglyph-releases-smart-qr-codes-and-smart-shortlinks.BR1b6zAf_Z2hhUo2.webp" alt="SnapGlyph Releases Smart QR Codes and Smart Shortlinks - Image generated using AI." loading="lazy" decoding="async" width="1200" height="676"></div><div class="newsroom-card-body"><div class="newsroom-card-meta"><span class="newsroom-tag" data-category="product">Product</span><time datetime="2026-05-09T00:00:00.000Z">May 9, 2026</time></div><h3>SnapGlyph Releases Smart QR Codes and Smart Shortlinks</h3><p>A single QR code or short link can now route to different destinations based on the day of the week or time of day, automatically.</p></div></a></div></section></div></div></main>
16<script>
17    (function () {
18      const archive = document.querySelector('.newsroom-archive');
19      if (!archive) return;
20      const chips = archive.querySelectorAll('.newsroom-chip');
21      chips.forEach((chip) => {
22        chip.addEventListener('click', () => {
23          const value = chip.getAttribute('data-filter') || 'all';
24          archive.setAttribute('data-active-category', value);
25          chips.forEach((c) => {
26            const active = c === chip;
27            c.classList.toggle('is-active', active);
28            c.setAttribute('aria-selected', active ? 'true' : 'false');
29          });
30        });
31      });
32    })();
33  </script>
33<footer class="footer"><div class="footer-container"><div class="footer-brand"><a href="/" class="footer-logo"><img src="/_astro/logo-light.BnTDjf0p_gExLD.svg" alt="SnapGlyph" loading="lazy" decoding="async" width="100" height="10"></a><p>QR codes, shortlinks, and link-in-bio pages.</p><address class="footer-address"><strong>SnapGlyph Software</strong><br>#1009 - 3909 University Ave NW<br>Calgary, AB, Canada T3B 6K3</address><div class="footer-social"><a href="https://www.linkedin.com/company/snapglyph" target="_blank" rel="noopener noreferrer" aria-label="SnapGlyph on LinkedIn" data-track="social_click" data-track-network="linkedin" data-track-location="footer"><svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M20.45 20.45h-3.56v-5.57c0-1.33-.02-3.04-1.85-3.04-1.85 0-2.14 1.45-2.14 2.94v5.67H9.34V9h3.42v1.56h.05c.48-.9 1.64-1.85 3.37-1.85 3.6 0 4.27 2.37 4.27 5.46v6.28zM5.34 7.43a2.07 2.07 0 1 1 0-4.13 2.07 2.07 0 0 1 0 4.13zM7.12 20.45H3.55V9h3.57v11.45zM22.22 0H1.77C.79 0 0 .77 0 1.73v20.54C0 23.22.79 24 1.77 24h20.45c.98 0 1.78-.78 1.78-1.73V1.73C24 .77 23.2 0 22.22 0z"></path></svg></a></div></div><div class="footer-links"><div class="footer-column"><h4>Product</h4><a href="/features/qr-codes/">QR Codes</a><a href="/features/url-shortener/">Link Shortener</a><a href="/features/link-in-bio/">Link in Bio</a><a href="/pricing/">Pricing</a><a href="/features/snapglyph-mcp/">SnapGlyph MCP</a></div><div class="footer-column"><h4>Company</h4><a href="/about/">About</a><a href="/contact/">Contact</a><a href="/news/">Newsroom</a><a href="/ai-instructions/">AI Instructions</a></div><div class="footer-column"><h4>Use Cases</h4><a href="/use-cases/business-owners/">For Business</a><a href="/use-cases/restaurants/">For Restaurants</a></div><div class="footer-column"><h4>Compare</h4><a href="/compare/">All Comparisons</a><a href="/compare/snapglyph-vs-linktree/">vs. Linktree</a><a href="/compare/snapglyph-vs-bitly/">vs. Bitly</a><a href="/compare/snapglyph-vs-beaconstac/">vs. Beaconstac</a><a href="/compare/snapglyph-vs-rebrandly/">vs. Rebrandly</a><a href="/compare/snapglyph-vs-beacons/">vs. Beacons</a></div><div class="footer-column"><h4>Resources</h4><a href="/support/" target="_blank">Support</a><a href="/blog/">Blog</a><a href="/faq/">FAQ</a><a href="https://app.snapglyph.com/docs/api" target="_blank" rel="noopener noreferrer">API Docs</a></div></div></div><div class="footer-bottom"><div class="footer-legal-links"><a href="/privacy/">Privacy Policy</a><a href="/terms/">Terms of Service</a><a href="/cookies/">Cookie Policy</a><a href="/subprocessors/">Subprocessors</a><button type="button" class="footer-cookie-btn" id="open-cookie-settings">Cookie Options</button><a href="https://status.snapglyph.com" target="_blank" rel="noopener noreferrer">Status</a></div><p>&copy; 2026 SnapGlyph Software. All rights reserved.</p></div></footer>
33<script>
34    // Mobile nav toggle
35    const mobileToggle = document.querySelector('.nav-mobile-toggle');
36    const mobileMenu = document.querySelector('.nav-mobile-menu');
37    const nav = document.querySelector('.nav');
38
39    if (nav) {
40      mobileToggle?.addEventListener('click', function() {
41        const isOpen = nav.classList.toggle('nav-open');
42        mobileToggle.setAttribute('aria-expanded', isOpen);
43      });
44
45      // Close menu when clicking a link (but not dropdown toggles)
46      document.querySelectorAll('.nav-mobile-menu a').forEach(link => {
47        link.addEventListener('click', () => {
48          nav.classList.remove('nav-open');
49          mobileToggle?.setAttribute('aria-expanded', 'false');
50        });
51      });
52
53      // Close menu when clicking outside
54      document.addEventListener('click', (e) => {
55        if (nav.classList.contains('nav-open') && !nav.contains(e.target)) {
56          nav.classList.remove('nav-open');
57          mobileToggle?.setAttribute('aria-expanded', 'false');
58        }
59      });
60
61      // Desktop dropdown toggles (supports multiple)
62      document.querySelectorAll('.nav-dropdown').forEach(dropdown => {
63        const toggle = dropdown.querySelector('.nav-dropdown-toggle');
64        toggle?.addEventListener('click', function(e) {
65          e.preventDefault();
66          // Close other open dropdowns
67          document.querySelectorAll('.nav-dropdown').forEach(other => {
68            if (other !== dropdown) {
69              other.classList.remove('nav-dropdown-open');
70              other.querySelector('.nav-dropdown-toggle')?.setAttribute('aria-expanded', 'false');
71            }
72          });
73          const isOpen = dropdown.classList.toggle('nav-dropdown-open');
74          toggle.setAttribute('aria-expanded', isOpen);
75        });
76      });
77
78      // Close desktop dropdowns when clicking outside
79      document.addEventListener('click', (e) => {
80        document.querySelectorAll('.nav-dropdown').forEach(dropdown => {
81          if (!dropdown.contains(e.target)) {
82            dropdown.classList.remove('nav-dropdown-open');
83            dropdown.querySelector('.nav-dropdown-toggle')?.setAttribute('aria-expanded', 'false');
84          }
85        });
86      });
87
88      // Mobile dropdown toggles (supports multiple)
89      document.querySelectorAll('.nav-mobile-dropdown').forEach(dropdown => {
90        const toggle = dropdown.querySelector('.nav-mobile-dropdown-toggle');
91        toggle?.addEventListener('click', function(e) {
92          e.preventDefault();
93          const isOpen = dropdown.classList.toggle('nav-mobile-dropdown-open');
94          toggle.setAttribute('aria-expanded', isOpen);
95        });
96      });
97    }
98  </script>
98<!-- Cookie Consent Banner --><div id="cookie-consent-banner" class="cookie-banner" style="display: none;"><div class="cookie-banner-content"><!-- Step 1: Initial View --><div id="cookie-step-1" class="cookie-step"><div class="cookie-banner-text"><h3>How we use Cookies</h3><p>We use cookies to enhance your experience and analyze site traffic.</p></div><div class="cookie-banner-actions"><button type="button" class="cookie-btn cookie-btn-secondary" id="cookie-customize">Customize</button><button type="button" class="cookie-btn cookie-btn-primary" id="cookie-accept-all">Accept All</button></div></div><!-- Step 2: Customize View --><div id="cookie-step-2" class="cookie-step" style="display: none;"><div class="cookie-banner-header"><button type="button" class="cookie-back-btn" id="cookie-back" aria-label="Go back"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 12L6 8L10 4"></path></svg></button><h3>Customize Cookies</h3></div><div class="cookie-options"><div class="cookie-option"><div class="cookie-option-left"><span class="cookie-option-label">Required</span><button type="button" class="cookie-info-btn" data-tooltip="Essential for the website to function properly" aria-label="More info"><svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0a8 8 0 100 16A8 8 0 008 0zm0 14.5a6.5 6.5 0 110-13 6.5 6.5 0 010 13zM8 6a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 018 6zm0-2.5a1 1 0 100 2 1 1 0 000-2z"></path></svg></button></div><div class="cookie-toggle cookie-toggle-required"><input type="checkbox" id="cookie-required" checked disabled><label for="cookie-required"></label></div></div><div class="cookie-option"><div class="cookie-option-left"><span class="cookie-option-label">Analytics</span><button type="button" class="cookie-info-btn" data-tooltip="Help us understand how visitors interact with our website" aria-label="More info"><svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0a8 8 0 100 16A8 8 0 008 0zm0 14.5a6.5 6.5 0 110-13 6.5 6.5 0 010 13zM8 6a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 018 6zm0-2.5a1 1 0 100 2 1 1 0 000-2z"></path></svg></button></div><div class="cookie-toggle"><input type="checkbox" id="cookie-analytics"><label for="cookie-analytics"></label></div></div><div class="cookie-option"><div class="cookie-option-left"><span class="cookie-option-label">Marketing</span><button type="button" class="cookie-info-btn" data-tooltip="Used to deliver relevant ads and track campaign performance" aria-label="More info"><svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0a8 8 0 100 16A8 8 0 008 0zm0 14.5a6.5 6.5 0 110-13 6.5 6.5 0 010 13zM8 6a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 018 6zm0-2.5a1 1 0 100 2 1 1 0 000-2z"></path></svg></button></div><div class="cookie-toggle"><input type="checkbox" id="cookie-marketing"><label for="cookie-marketing"></label></div></div><div class="cookie-option"><div class="cookie-option-left"><span class="cookie-option-label">Advertising</span><button type="button" class="cookie-info-btn" data-tooltip="Enable personalized advertising across platforms" aria-label="More info"><svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0a8 8 0 100 16A8 8 0 008 0zm0 14.5a6.5 6.5 0 110-13 6.5 6.5 0 010 13zM8 6a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 018 6zm0-2.5a1 1 0 100 2 1 1 0 000-2z"></path></svg></button></div><div class="cookie-toggle"><input type="checkbox" id="cookie-advertising"><label for="cookie-advertising"></label></div></div></div><div class="cookie-banner-actions"><button type="button" class="cookie-btn cookie-btn-secondary" id="cookie-reject-all">Reject All</button><button type="button" class="cookie-btn cookie-btn-primary" id="cookie-save-choices">Save Choices</button></div></div></div></div>
98<script>
99    (function() {
100      const COOKIE_NAME = 'snapglyph_cookie_consent';
101      const COOKIE_EXPIRY_DAYS = 365;
102
103      // Get cookie value
104      function getCookie(name) {
105        const value = `; ${document.cookie}`;
106        const parts = value.split(`; ${name}=`);
107        if (parts.length === 2) return parts.pop().split(';').shift();
108        return null;
109      }
110
111      // Set cookie with expiry
112      function setCookie(name, value, days) {
113        const date = new Date();
114        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
115        const expires = `expires=${date.toUTCString()}`;
116        document.cookie = `${name}=${value};${expires};path=/;SameSite=Lax`;
117      }
118
119      // Push consent to GTM dataLayer and update Google Consent Mode v2
120      function pushConsentToGTM(consent) {
121        window.dataLayer = window.dataLayer || [];
122
123        // Google Consent Mode v2 update
124        function gtag(){dataLayer.push(arguments);}
125        gtag('consent', 'update', {
126          'analytics_storage': consent.analytics ? 'granted' : 'denied',
127          'ad_storage': consent.advertising ? 'granted' : 'denied',
128          'ad_user_data': consent.marketing ? 'granted' : 'denied',
129          'ad_personalization': consent.advertising ? 'granted' : 'denied'
130        });
131
132        // Custom dataLayer events for GTM triggers
133        window.dataLayer.push({
134          'event': 'cookie_consent_update',
135          'cookie_consent_analytics': consent.analytics,
136          'cookie_consent_marketing': consent.marketing,
137          'cookie_consent_advertising': consent.advertising
138        });
139
140        if (consent.analytics) {
141          window.dataLayer.push({ 'event': 'consent_analytics' });
142        }
143        if (consent.marketing) {
144          window.dataLayer.push({ 'event': 'consent_marketing' });
145        }
146        if (consent.advertising) {
147          window.dataLayer.push({ 'event': 'consent_advertising' });
148        }
149      }
150
151      // Save preferences
152      function savePreferences(analytics, marketing, advertising) {
153        const consent = {
154          required: true,
155          analytics: analytics,
156          marketing: marketing,
157          advertising: advertising,
158          timestamp: new Date().toISOString()
159        };
160        setCookie(COOKIE_NAME, JSON.stringify(consent), COOKIE_EXPIRY_DAYS);
161        pushConsentToGTM(consent);
162        hideBanner();
163      }
164
165      // Show banner
166      function showBanner(showCustomize) {
167        const banner = document.getElementById('cookie-consent-banner');
168        const step1 = document.getElementById('cookie-step-1');
169        const step2 = document.getElementById('cookie-step-2');
170
171        if (banner) {
172          // Show appropriate step
173          if (showCustomize) {
174            step1.style.display = 'none';
175            step2.style.display = 'block';
176          } else {
177            step1.style.display = 'block';
178            step2.style.display = 'none';
179          }
180          banner.style.display = 'flex';
181          setTimeout(() => banner.classList.add('cookie-banner-visible'), 10);
182        }
183      }
184
185      // Hide banner
186      function hideBanner() {
187        const banner = document.getElementById('cookie-consent-banner');
188        if (banner) {
189          banner.classList.remove('cookie-banner-visible');
190          setTimeout(() => {
191            banner.style.display = 'none';
192            // Reset to step 1
193            document.getElementById('cookie-step-1').style.display = 'block';
194            document.getElementById('cookie-step-2').style.display = 'none';
195          }, 300);
196        }
197      }
198
199      // Switch to customize view
200      function showCustomizeStep() {
201        const step1 = document.getElementById('cookie-step-1');
202        const step2 = document.getElementById('cookie-step-2');
203        step1.style.display = 'none';
204        step2.style.display = 'block';
205      }
206
207      // Switch back to initial view
208      function showInitialStep() {
209        const step1 = document.getElementById('cookie-step-1');
210        const step2 = document.getElementById('cookie-step-2');
211        step1.style.display = 'block';
212        step2.style.display = 'none';
213      }
214
215      // Load saved preferences into checkboxes
216      function loadPreferencesIntoUI(consent) {
217        document.getElementById('cookie-analytics').checked = consent.analytics;
218        document.getElementById('cookie-marketing').checked = consent.marketing;
219        document.getElementById('cookie-advertising').checked = consent.advertising;
220      }
221
222      // Initialize on DOM ready
223      function init() {
224        const acceptAllBtn = document.getElementById('cookie-accept-all');
225        const rejectAllBtn = document.getElementById('cookie-reject-all');
226        const customizeBtn = document.getElementById('cookie-customize');
227        const backBtn = document.getElementById('cookie-back');
228        const saveChoicesBtn = document.getElementById('cookie-save-choices');
229        const openSettingsBtn = document.getElementById('open-cookie-settings');
230
231        // Check for existing consent
232        const existingConsent = getCookie(COOKIE_NAME);
233
234        if (existingConsent) {
235          try {
236            const consent = JSON.parse(existingConsent);
237            loadPreferencesIntoUI(consent);
238            pushConsentToGTM(consent);
239          } catch (e) {
240            showBanner(false);
241          }
242        } else {
243          showBanner(false);
244        }
245
246        // Accept all
247        acceptAllBtn?.addEventListener('click', function() {
248          savePreferences(true, true, true);
249        });
250
251        // Customize button - go to step 2
252        customizeBtn?.addEventListener('click', function() {
253          showCustomizeStep();
254        });
255
256        // Back button - go to step 1
257        backBtn?.addEventListener('click', function() {
258          showInitialStep();
259        });
260
261        // Reject all (only required cookies)
262        rejectAllBtn?.addEventListener('click', function() {
263          savePreferences(false, false, false);
264        });
265
266        // Save current choices
267        saveChoicesBtn?.addEventListener('click', function() {
268          const analytics = document.getElementById('cookie-analytics').checked;
269          const marketing = document.getElementById('cookie-marketing').checked;
270          const advertising = document.getElementById('cookie-advertising').checked;
271          savePreferences(analytics, marketing, advertising);
272        });
273
274        // Open cookie settings from footer - go directly to customize
275        openSettingsBtn?.addEventListener('click', function() {
276          const existingConsent = getCookie(COOKIE_NAME);
277          if (existingConsent) {
278            try {
279              const consent = JSON.parse(existingConsent);
280              loadPreferencesIntoUI(consent);
281            } catch (e) {}
282          }
283          showBanner(true);
284        });
285
286        // Tooltip functionality for info buttons
287        document.querySelectorAll('.cookie-info-btn').forEach(function(btn) {
288          // For touch devices
289          btn.addEventListener('click', function(e) {
290            e.preventDefault();
291            const allTooltips = document.querySelectorAll('.cookie-info-btn');
292            allTooltips.forEach(function(t) {
293              if (t !== btn) t.classList.remove('tooltip-active');
294            });
295            btn.classList.toggle('tooltip-active');
296          });
297        });
298
299        // Close tooltips when clicking outside
300        document.addEventListener('click', function(e) {
301          if (!e.target.closest('.cookie-info-btn')) {
302            document.querySelectorAll('.cookie-info-btn').forEach(function(btn) {
303              btn.classList.remove('tooltip-active');
304            });
305          }
306        });
307      }
308
309      if (document.readyState === 'loading') {
310        document.addEventListener('DOMContentLoaded', init);
311      } else {
312        init();
313      }
314    })();
315  </script>
315<!-- Event Tracking -->
315<script>
316    (function() {
317      // GA4 Event Tracking via dataLayer
318      function trackEvent(eventName, eventParams) {
319        window.dataLayer = window.dataLayer || [];
320        window.dataLayer.push({
321          event: eventName,
322          ...eventParams
323        });
324      }
325
326      // Handle clicks on tracked elements
327      document.addEventListener('click', function(e) {
328        const tracked = e.target.closest('[data-track]');
329        if (!tracked) return;
330
331        const eventName = tracked.dataset.track;
332        const params = {};
333
334        // Collect all data-track-* attributes as event parameters
335        for (const attr of tracked.attributes) {
336          if (attr.name.startsWith('data-track-') && attr.name !== 'data-track') {
337            const paramName = attr.name.replace('data-track-', '').replace(/-/g, '_');
338            params[paramName] = attr.value;
339          }
340        }
341
342        trackEvent(eventName, params);
343      });
344
345      // Expose trackEvent globally for programmatic use (e.g., pricing toggle)
346      window.snapglyphTrack = trackEvent;
347    })();
348  </script>
348</body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.