1/** 2 * MapsShop entry-point onboarding banner. 3 * 4 * Background (S66-2, follow-up to the 27 May UX-regression briefing) 5 * ------------------------------------------------------------------ 6 * MapsShop.ru is the storefront: a customer buys a city map there, gets an 7 * email with a link to osm2cdr.ru, lands here, and does not understand how to 8 * download "their" map ("как ÑкаÑаÑÑ / непонÑÑÐ½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°ÑиÑ"). 6 such 9 * complaints in 18-25 May. The existing Open-Beta / Format-Wizard / post-gen 10 * banners do NOT cover this entry-point case. 11 * 12 * This banner is shown ONLY to visitors arriving from MapsShop and gives a 13 * 1-2-3 navigation hint (select area -> pick format -> Create -> file in ~30s, 14 * no signup). Regular visitors never see it. 15 * 16 * Detection (any one signal is enough): 17 * - ``utm_source=mapsshop`` query param (canonical â MapsShop email links 18 * can/should carry it; the funnel tracker in map.js already reads UTM). 19 * - ``document.referrer`` host contains "mapsshop" (best-effort fallback for 20 * links that lack the UTM tag; referrer can be empty under strict 21 * referrer-policy, hence the UTM param is the primary signal). 22 * 23 * Dismiss is persisted in localStorage so the hint is shown at most once. 24 * 25 * Progressive enhancement: the banner markup starts hidden (CSS ``hidden`` 26 * class) and is only revealed by this script, so visitors with JS disabled â 27 * and every non-MapsShop visitor â never see it. This is the inverse of the 28 * Open-Beta banner (which is shown by default); here the default is hidden. 29 * 30 * Security: all banner text is static, localized via ``data-i18n`` (textContent, 31 * not innerHTML), so no user-controlled value (referrer / UTM) is ever written 32 * into the DOM. Detection only reads those values for boolean matching. 33 */ 34(function () { 35 'use strict'; 36 37 var STORAGE_KEY = 'mapsshop_banner_dismissed_v1'; 38 var MARKER = 'mapsshop'; 39 40 /** 41 * @returns {boolean} true if this visit looks like it came from MapsShop. 42 */ 43 function cameFromMapsShop() { 44 // Signal 1: explicit utm_source=mapsshop (case-insensitive). 45 try { 46 var params = new URLSearchParams(window.location.search); 47 var src = (params.get('utm_source') || '').toLowerCase(); 48 if (src.indexOf(MARKER) !== -1) { 49 return true; 50 } 51 } catch (e) { 52 // URLSearchParams unavailable â fall through to referrer check. 53 } 54 55 // Signal 2: referrer host contains "mapsshop" (best-effort; may be empty 56 // under a strict referrer policy, which is why UTM is the primary signal). 57 try { 58 var ref = (document.referrer || '').toLowerCase(); 59 if (ref.indexOf(MARKER) !== -1) { 60 return true; 61 } 62 } catch (e) { 63 // referrer access blocked â ignore. 64 } 65 66 return false; 67 } 68 69 function init() { 70 var banner = document.getElementById('mapsShopBanner'); 71 if (!banner) { 72 return; 73 } 74 75 // Show only for MapsShop arrivals â every other visitor keeps the 76 // default-hidden state. 77 if (!cameFromMapsShop()) { 78 return; 79 } 80 81 // Already dismissed in a previous visit â stay hidden. 82 try { 83 if (window.localStorage && localStorage.getItem(STORAGE_KEY) === '1') { 84 return; 85 } 86 } catch (e) { 87 // localStorage unavailable (private mode) â show the banner this view. 88 } 89 90 banner.classList.remove('hidden'); 91 92 var dismissBtn = banner.querySelector('.mapsshop-banner-dismiss'); 93 if (dismissBtn) { 94 dismissBtn.addEventListener('click', function () { 95 banner.classList.add('hidden'); 96 try { 97 if (window.localStorage) { 98 localStorage.setItem(STORAGE_KEY, '1'); 99 } 100 } catch (e) { 101 // Storage blocked â hide for this page view only. 102 } 103 }); 104 } 105 } 106 107 if (document.readyState === 'loading') { 108 document.addEventListener('DOMContentLoaded', init); 109 } else { 110 init(); 111 } 112})();
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.