/* ============================================================================ IDX CONFIGURATION — THE ONLY FILE YOU EDIT TO SWAP MLS PROVIDERS ============================================================================ Every "Search / View Listings" action on this site is built here and sent to Seenu's eXp BoldTrail (kvCORE) IDX, which carries every active Calgary-area MLS® listing in real time. ─────────────────────────────────────────────────────────────────────────── HOW THIS IDX WORKS (important): ─────────────────────────────────────────────────────────────────────────── BoldTrail does NOT use free-text search URLs. Each place is selected by a unique geo-code called "pak" (e.g. pak=city:g30_c3nfkdtg for Calgary). So to deep-link a place, we need its exact pak code. They're listed in PLACES below. To ADD a new place: 1. Go to seenugeorge.exprealty.com and search that place. 2. Copy the URL — find the &display=... and &pak=city:... parts. 3. Add a new line to PLACES below. ─────────────────────────────────────────────────────────────────────────── WHEN SEENU LEAVES eXp (or changes IDX provider): ─────────────────────────────────────────────────────────────────────────── 1. Change BASE_URL + SEARCH_PATH to the new provider. 2. Re-map the PARAM names in buildUrl() to the new provider's params. 3. Re-capture the place codes (or the new provider may use plain text). 4. Update COMPLIANCE if the brokerage/data source changes. RECOMMENDED: point a branded subdomain (search.homesbyseenu.ca) at BoldTrail in Hostinger DNS, then set BASE_URL to it — future swaps become 1 DNS change. ============================================================================ */ window.IDX = { // ---- 1. IDX site root + search path -------------------------------------- BASE_URL: 'https://seenugeorge.exprealty.com', // BASE_URL: 'https://search.homesbyseenu.ca', // <- future branded subdomain SEARCH_PATH: '/index.php', // Lead-capture / account registration page (the "customer grab" portal). // Registrations land in Seenu's BoldTrail (kvCORE) CRM. REGISTER_PATH: '/login.php?login=1', // Real contact details: PHONE: '+1 (403) 828-2359', PHONE_RAW: '+14038282359', EMAIL: 'seenu@homesbyseenu.ca', TITLE: 'Real Estate Advisor', // Real brokerage office: OFFICE: { brokerage: 'eXp Realty — Calgary', addr1: '#700 – 1816 Crowchild Trail NW', city: 'Calgary, AB T2M 3Y7', phone: '+1 (403) 828-2359', support: '833-497-4422', }, INSTAGRAM: 'https://www.instagram.com/seenugeorge3/reels/', // ---- Contact form delivery ---------------------------------------------- // The contact form emails submissions here via FormSubmit.co (no API key). // On the FIRST real submission from the live site, FormSubmit sends a // one-time confirmation email to this address — open it and click the link // once, and every submission after that is delivered automatically. CONTACT_EMAIL: 'seenu@homesbyseenu.ca', // ---- Named BoldTrail destinations (real URLs) ---------------------------- // Wired to buttons across the site. Edit a path here → every button updates. LINKS: { allListings: '/index.php?advanced=1&display=&custombox=&types[]=1&beds=0&baths=0&min=0&max=100000000#rslt', ourListings: '/index.php?showagency=1#rslt', // Seenu's own listings justListed: '/index.php?quick=1&display=&custombox=&types[]=1&types[]=2&types[]=3&types[]=4&types[]=5&types[]=6&types[]=9&types[]=12&types[]=17&types[]=39&types[]=45&beds=0&baths=0&min=0&max=100000000&minfootage=0&maxfootage=30000&minacres=0&maxacres=50000&yearbuilt=0&walkscore=0&options[]=new&keywords=&rtype=grid&sortby=listings.price+DESC#rslt', justReduced: '/index.php?quick=1&display=&custombox=&types[]=1&types[]=2&types[]=3&types[]=4&types[]=5&types[]=6&types[]=9&types[]=12&types[]=17&types[]=39&types[]=45&beds=0&baths=0&min=0&max=100000000&minfootage=0&maxfootage=30000&minacres=0&maxacres=50000&yearbuilt=0&walkscore=0&options[]=reduced&keywords=&rtype=grid&sortby=listings.price+DESC#rslt', valuation: '/seller/valuation/', // "What's My Home Worth?" alerts: '/login.php?login=1', // Instant listing alerts / free account resources: '/resources.php', // Buyer & Seller resources finance: '/finance.php', // Get pre-approved contactIdx: '/contact.php', // BoldTrail contact form advanced: '/index.php?advanced=1', // Full advanced search (all filters) }, // ---- 2. Places (real BoldTrail pak codes) -------------------------------- // Key = the label you reference in the site. Add more by capturing URLs. PLACES: { 'Calgary': { display: 'Calgary', pak: 'city:g30_c3nfkdtg' }, 'Airdrie': { display: 'Airdrie', pak: 'city:g30_c3ngv8qq' }, 'Cochrane': { display: 'Cochrane', pak: 'city:g30_c3ne5jyh' }, 'Chestermere': { display: 'Chestermere', pak: 'city:g30_c3p43f7s' }, 'Canmore': { display: 'Canmore', pak: 'city:g30_c3jfrxyd' }, 'Banff': { display: 'Banff', pak: 'city:g30_c3jg4hrh' }, 'High River': { display: 'High River', pak: 'city:g30_c2zpbb65' }, 'Okotoks': { display: 'Okotoks', pak: 'city:g30_c3nbwdhb' }, // ── TO ADD CALGARY NEIGHBOURHOODS (Mount Royal, Britannia, Aspen…) ── // Search the neighbourhood on BoldTrail, copy its &display / &pak, add here: // 'Mount Royal': { display: 'Mount Royal', pak: 'city:XXXX' }, }, // Where a non-place search ("Open Full MLS Search") should land. The site // homepage always carries a working search, so it's the safe catch-all. HOME_SEARCH: '/', // ---- 3. Legal / compliance line ------------------------------------------ // Official Pillar 9™ / CREA® MLS® disclaimer (required by the data licence). COMPLIANCE: 'Data is supplied by Pillar 9™ MLS® System. Pillar 9™ is the owner of the copyright in its MLS® System. ' + 'Data is deemed reliable but is not guaranteed accurate by Pillar 9™. The trademarks MLS®, Multiple Listing ' + 'Service® and the associated logos are owned by The Canadian Real Estate Association (CREA®) and identify the ' + 'quality of services provided by real estate professionals who are members of CREA®. Used under license. ' + 'Seenu George is a licensed REALTOR® with eXp Realty. Listing search powered by BoldTrail.', }; /* ---------------------------------------------------------------------------- URL builder. Call window.idxSearch({ place, minPrice, maxPrice, beds, baths }). - place: a key from PLACES (e.g. 'Calgary'). Omit for a general search. - all filters optional. Edit the param names in ONE spot here if you ever change providers. ---------------------------------------------------------------------------- */ window.idxSearch = function idxSearch(opts) { opts = opts || {}; const cfg = window.IDX; const base = cfg.BASE_URL.replace(/\/$/, ''); const place = opts.place ? cfg.PLACES[opts.place] : null; // No known place → go to the homepage search (always works). if (!place && !opts.place) { return base + cfg.HOME_SEARCH; } // Build the query string MANUALLY so the pak colon stays literal (city:g30_…), // exactly matching BoldTrail's working URL format (URLSearchParams would // percent-encode the colon to %3A). const enc = encodeURIComponent; const parts = [ 'advanced=1', 'rtype=map', 'minacres=0', 'maxacres=50000', 'minfootage=0', 'maxfootage=30000', ]; if (place) { parts.push('display=' + enc(place.display)); parts.push('pak=' + place.pak); // literal colon preserved } else if (opts.place) { parts.push('display=' + enc(opts.place)); } parts.push('beds=' + (opts.beds || 0)); parts.push('baths=' + (opts.baths || 0)); parts.push('min=' + (opts.minPrice || 0)); parts.push('max=' + (opts.maxPrice || 100000000)); return base + cfg.SEARCH_PATH + '?' + parts.join('&'); }; // Fire the Google Ads conversion when handing a visitor off to BoldTrail. // Runs on OUR domain (where the ad click/gclid lives) so the conversion is // correctly attributed — no fragile cross-domain tracking needed. // Click-ID gating: only fires for visitors who arrived via a Google ad (gclid) // or Microsoft ad (msclkid) — captured on landing and kept 90 days. Organic / // direct / typed-in traffic never triggers a mis-attributed conversion. window.__sgCaptureClickIds = function () { try { var p = new URLSearchParams(window.location.search); ['gclid', 'msclkid'].forEach(function (k) { var v = p.get(k); if (v) { localStorage.setItem('sg_' + k, v); localStorage.setItem('sg_' + k + '_ts', String(Date.now())); } }); // Capture UTM campaign tags (set on your ad Final URLs) so alerts + lead // notes can show WHICH campaign / keyword drove the visit. Kept 90 days. ['utm_source', 'utm_campaign', 'utm_term', 'utm_content', 'utm_medium'].forEach(function (k) { var v = p.get(k); if (v) { localStorage.setItem('sg_' + k, v); localStorage.setItem('sg_utm_ts', String(Date.now())); } }); } catch (e) {} }; window.__sgUtm = function () { try { var ts = parseInt(localStorage.getItem('sg_utm_ts') || '0', 10); if (!ts || Date.now() - ts > 90 * 864e5) return null; var g = function (k) { return localStorage.getItem('sg_' + k) || ''; }; var campaign = g('utm_campaign'), term = g('utm_term'), source = g('utm_source'); if (!campaign && !term && !source) return null; return { source: source, campaign: campaign, term: term, content: g('utm_content'), medium: g('utm_medium') }; } catch (e) { return null; } }; window.__sgUtmText = function () { var u = window.__sgUtm(); if (!u) return ''; var parts = []; if (u.source) parts.push(u.source); if (u.campaign) parts.push('campaign: ' + u.campaign); if (u.term) parts.push('keyword: ' + u.term); return parts.join(' · '); }; window.__sgHasClickId = function (key) { try { var ts = parseInt(localStorage.getItem('sg_' + key + '_ts') || '0', 10); if (!ts || Date.now() - ts > 90 * 864e5) return false; return !!localStorage.getItem('sg_' + key); } catch (e) { return false; } }; try { window.__sgCaptureClickIds(); } catch (e) {} window.fireIdxConversion = function fireIdxConversion() { try { if (window.__sgHasClickId('gclid') && window.gtag) { window.gtag('event', 'conversion', { send_to: 'AW-18217550252/tCIiCMjri78cEKyD5-5D' }); } } catch (e) {} }; // (Removed) Anonymous "search/browse" heads-up email — it generated noise. // Only real form submissions notify Seenu now. // Append the Google (gclid) and Microsoft (msclkid) ad-click IDs to a BoldTrail // URL so a registration there can be attributed back to the ad that started on // homesbyseenu.ca. Reads from the URL or the IDs we saved on first arrival. window.__sgWithClickIds = function (url) { try { var p = new URLSearchParams(window.location.search); var get = function (k) { return p.get(k) || (function () { try { return localStorage.getItem('sg_' + k); } catch (e) { return null; } })(); }; var g = get('gclid'), m = get('msclkid'); var extra = []; if (g) extra.push('gclid=' + encodeURIComponent(g)); if (m) extra.push('msclkid=' + encodeURIComponent(m)); if (!extra.length) return url; return url + (url.indexOf('?') === -1 ? '?' : '&') + extra.join('&'); } catch (e) { return url; } }; // Open the IDX search in a new tab (keeps the brand site open behind it). // No analytics event here; browsing is not a conversion. We pass the ad-click // IDs through so BoldTrail can attribute any registration to the ad. window.openIdxSearch = function openIdxSearch(opts) { window.open(window.__sgWithClickIds(window.idxSearch(opts)), '_blank', 'noopener'); }; // List of place keys for dropdowns window.idxPlaces = function idxPlaces() { return Object.keys(window.IDX.PLACES); }; // Open the BoldTrail lead-capture / account registration page in a new tab. window.openIdxRegister = function openIdxRegister() { // Microsoft UET: record a "Register" event ONLY for Microsoft ad visitors if (window.uetq && window.__sgHasClickId('msclkid')) { window.uetq.push('event', 'register', { 'event_category': 'Lead', 'event_label': 'Register / Pre-approval' }); } window.open(window.__sgWithClickIds(window.IDX.BASE_URL.replace(/\/$/, '') + window.IDX.REGISTER_PATH), '_blank', 'noopener'); }; // Build / open a named BoldTrail destination (see IDX.LINKS above). window.idxLink = function idxLink(key) { const cfg = window.IDX; const path = cfg.LINKS[key]; if (!path) return cfg.BASE_URL.replace(/\/$/, '') + cfg.HOME_SEARCH; return cfg.BASE_URL.replace(/\/$/, '') + path; }; window.openIdxLink = function openIdxLink(key) { window.open(window.__sgWithClickIds(window.idxLink(key)), '_blank', 'noopener'); }; /* ---- Back-compat shims so existing calls keep working --------------------- */ window.idxUrl = function (kind, params) { params = params || {}; return window.idxSearch({ place: params.keyword, // old "keyword" → treat as place name minPrice: params.minPrice, maxPrice: params.maxPrice, beds: params.beds, }); }; window.openIdx = function (kind, params) { window.open(window.idxUrl(kind, params), '_blank', 'noopener'); };