1<!DOCTYPE html> 2 <!-- Published 8473af40-b4e5-4874-b493-8107d6e8d69c created by Magic Patterns: https://www.magicpatterns.com/ --> 3 <html lang="en" dir="ltr" style="overflow:auto;" class="light"> 4 <head> 5 <meta charset="UTF-8" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge" /> 8 <title>Keyanalyzer Tools & Software Reviews Landing Page</title> 9 <meta property="og:title" content="Keyanalyzer Tools & Software Reviews Landing Page" /> 10 11 12 13 <meta property="og:type" content="website" /> 14 15 <link rel="stylesheet" type="text/css" href="https://cdn.magicpatterns.com/patterns/bundles/4a46f471-f788-4f0c-a84e-c171a585c076/4dbe33ee-daf7-4c02-8fd5-741f739e35e4/index-4a46f471-f788-4f0c-a84e-c171a585c076.css" crossorigin="anonymous"> 16 <link rel="preconnect" href="https://fonts.googleapis.com"> 17 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 18 <link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet"> 19 20 21 </head> 22 <body style="margin:0;font-family:"'Inter','Inter',sans-serif;"> 23 24 <style> 25 @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap'); 26 .mp-badge .close-btn { opacity: 0; pointer-events: none; } 27 .mp-badge:hover .close-btn { opacity: 1; pointer-events: auto; } 28 </style> 29 <div 30 class="mp-badge" 31 style="position: fixed; bottom: 16px; right: 16px; z-index: 99999; font-family: 'Poppins', ui-sans-serif, system-ui, sans-serif;"> 32 <div class="close-btn" 33 aria-label="Close Magic Patterns Badge" 34 onclick="event.stopPropagation(); this.parentElement.style.display='none';" 35 style=" 36 position: absolute; 37 top: -8px; 38 right: -8px; 39 width: 18px; 40 height: 18px; 41 font-size: 12px; 42 cursor: pointer; 43 color: rgba(0,22,23,0.55); 44 font-family: 'Poppins', ui-sans-serif, system-ui, sans-serif; 45 line-height: 18px; 46 text-align: center; 47 background-color: #FFFFFF; 48 border-radius: 9999px; 49 display: flex; 50 align-items: center; 51 justify-content: center; 52 transition: all 0.15s ease; 53 z-index: 1; 54 user-select: none; 55 box-shadow: 0 1px 3px rgba(0,22,23,0.12); 56 border: 1px solid rgba(0,22,23,0.12);" 57 > 58 <svg width="6" height="6" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg" style="display: block;"> 59 <path d="M1 1L9 9M9 1L1 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/> 60 </svg> 61 </div> 62 <a target="_blank" href="https://www.magicpatterns.com/c/4ju4cydebw38zu2jxejqm1" style=" 63 border-radius: 9999px; 64 border: 1px solid rgba(0,22,23,0.12); 65 display: flex; 66 align-items: center; 67 gap: 8px; 68 padding: 8px 16px 8px 14px; 69 box-shadow: 0 2px 8px rgba(0,22,23,0.08), 0 1px 2px rgba(0,22,23,0.06); 70 cursor: pointer; 71 transition: box-shadow 0.2s ease; 72 text-decoration: none; 73 background: #FFFFFF;" 74 onmouseenter="this.style.boxShadow='0 4px 14px rgba(0,22,23,0.12), 0 2px 4px rgba(0,22,23,0.08)';" 75 onmouseleave="this.style.boxShadow='0 2px 8px rgba(0,22,23,0.08), 0 1px 2px rgba(0,22,23,0.06)';" 76 > 77 <img src="https://www.magicpatterns.com/MP_logo.png" alt="Magic Patterns" style=" 78 height: 18px; 79 width: auto; 80 display: block; 81 position: relative; 82 z-index: 1; 83 "> 84 <span style="font-family: 'Poppins', ui-sans-serif, system-ui, sans-serif; font-size: 14px; font-weight: 500; color: rgb(0,22,23);"> 85 Built with Magic Patterns 86 </span> 87 </a> 88 </div> 89 90 <div id="root" /> 91 92 93 94 95 96
96<script src="https://cdn.magicpatterns.com/patterns/bundles/4a46f471-f788-4f0c-a84e-c171a585c076/4dbe33ee-daf7-4c02-8fd5-741f739e35e4/index-4a46f471-f788-4f0c-a84e-c171a585c076.js" type="module" crossorigin="anonymous" async></script>
96 97
97<script> 98(function() { 99 // Track the last known path to avoid duplicate messages 100 let lastPath = window.location.pathname; 101 102 // Helper function to notify parent of route changes 103 function notifyRouteChange(path) { 104 if (path !== lastPath) { 105 lastPath = path; 106 window.parent.postMessage({ 107 id: '0a4de6fe-f55e-4963-94a1-47a0c1a6f901', 108 type: 'ROUTE_CHANGED', 109 path: path 110 }, '*'); 111 } 112 } 113 114 // Override pushState 115 const originalPushState = history.pushState; 116 history.pushState = function() { 117 originalPushState.apply(history, arguments); 118 notifyRouteChange(window.location.pathname); 119 }; 120 121 // Override replaceState 122 const originalReplaceState = history.replaceState; 123 history.replaceState = function() { 124 originalReplaceState.apply(history, arguments); 125 notifyRouteChange(window.location.pathname); 126 }; 127 128 // Listen for popstate (browser back/forward) 129 window.addEventListener('popstate', function() { 130 notifyRouteChange(window.location.pathname); 131 }); 132 133 // Listen for hash changes 134 window.addEventListener('hashchange', function() { 135 notifyRouteChange(window.location.pathname + window.location.hash); 136 }); 137 138 // Also monitor clicks for client-side routing that might not use History API 139 // This is a fallback for edge cases 140 let checkInterval; 141 document.addEventListener('click', function(e) { 142 // Clear any existing interval 143 if (checkInterval) clearInterval(checkInterval); 144 145 // Check for route changes over the next 100ms 146 let checks = 0; 147 checkInterval = setInterval(function() { 148 checks++; 149 const currentPath = window.location.pathname; 150 if (currentPath !== lastPath) { 151 notifyRouteChange(currentPath); 152 clearInterval(checkInterval); 153 } 154 // Stop checking after 10 attempts (100ms total) 155 if (checks >= 10) { 156 clearInterval(checkInterval); 157 } 158 }, 10); 159 }); 160 161 // Notify parent of initial path on load 162 window.addEventListener('load', function() { 163 window.parent.postMessage({ 164 id: '0a4de6fe-f55e-4963-94a1-47a0c1a6f901', 165 type: 'ROUTE_CHANGED', 166 path: window.location.pathname 167 }, '*'); 168 }); 169})(); 170</script>
170 171 172 173 174 175 176 177 178 179 180
180<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"e867a81586484a148de12267bf4d1b46","spa":2}' crossorigin="anonymous"></script>
180 181</body> 182 </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.