A Estero window treatment specialist will text you within 15 minutes to confirm your free consultation. No phone tag, no waiting around—real humans, real fast.
"
* OR: Code Snippets plugin → new PHP/HTML snippet on wp_footer.
* Runs on every page. Any Avada form that has hidden fields with the
* exact names listed below will be auto-filled at page load AND just before submit.
*
* Avada Form note: Avada renders — NOT
* the form-prefixed format. So we target by exact name.
*
* Required hidden fields to add inside the Avada Form 4823 (and any other form
* that should capture attribution). Field "Name" must match exactly:
* utm_source, utm_medium, utm_campaign, utm_term, utm_content, utm_id,
* gclid, gbraid, wbraid, fbclid, msclkid,
* campaignname, adgroup, adgroupname, matchtype, network, device, placement,
* targetid, loc_physical, loc_interest,
* page_url, page_title, referrer, landing_page, landing_referrer, submitted_at,
* geo_city, geo_region, geo_zip, geo_country, user_agent
*/
(function(){
'use strict';// ---------- helpers ----------
function getParam(name){
var m = window.location.search.match(new RegExp('[?&]' + name + '=([^&]*)'));
return m ? decodeURIComponent(m[1].replace(/\+/g,' ')) : '';
}function setField(fieldName, value){
if (value == null || value === '') return;
var nodes = document.querySelectorAll(
'input[name="' + fieldName + '"], ' +
'input[name$="-' + fieldName + '"]' // tolerate prefixed naming
);
for (var i = 0; i < nodes.length; i++) {
if (!nodes[i].value) nodes[i].value = value;
}
}function setAll(map){
Object.keys(map).forEach(function(k){ setField(k, map[k]); });
}// ---------- 1. Read every relevant URL param ----------
function readUrlParams(){
var paramNames = [
'utm_source','utm_medium','utm_campaign','utm_term','utm_content','utm_id',
'gclid','gbraid','wbraid','fbclid','msclkid',
'campaignname','adgroup','adgroupname',
'matchtype','network','device','placement',
'targetid','loc_physical','loc_interest'
];
var out = {};
paramNames.forEach(function(n){ out[n] = getParam(n); });
return out;
}// ---------- 2. First-touch persistence ----------
// Keeps original attribution if the visitor lands on a UTM URL, browses,
// then submits from a clean URL.
function firstTouchMerge(current){
try {
var stored = sessionStorage.getItem('ev_first_touch');
var firstTouch = stored ? JSON.parse(stored) : null;// Save on first paid/tracked hit
if (!firstTouch && (current.utm_source || current.gclid || current.gbraid || current.wbraid || current.fbclid || current.msclkid)) {
firstTouch = Object.assign({}, current, {
landing_page: window.location.href,
landing_referrer: document.referrer || '(direct)'
});
sessionStorage.setItem('ev_first_touch', JSON.stringify(firstTouch));
}// Backfill from first-touch when current URL is clean
if (firstTouch) {
Object.keys(firstTouch).forEach(function(k){
if (!current[k]) current[k] = firstTouch[k];
});
}
} catch(e){ /* sessionStorage blocked → ignore */ }
return current;
}// ---------- 3. Page context ----------
function pageContext(){
return {
page_url: window.location.href,
page_title: document.title,
referrer: document.referrer || '(direct)',
submitted_at: new Date().toISOString(),
user_agent: navigator.userAgent
};
}// ---------- 4. Geo (Cloudflare trace, free, no key) ----------
// Cloudflare exposes /cdn-cgi/trace on every CF-fronted site (evblinds.com is on CF).
// We pull loc + ip in one HEAD-weight request, cached for the session.
function loadGeo(cb){
try {
var cached = sessionStorage.getItem('ev_geo');
if (cached) { cb(JSON.parse(cached)); return; }
} catch(e){}// Cloudflare gives us country only via trace. For city/region/zip
// we hit a free no-key endpoint as a soft enrichment. Both are non-blocking.
var geo = { geo_country: '', geo_city: '', geo_region: '', geo_zip: '' };
var pending = 2;
function done(){ if(--pending===0){ try{sessionStorage.setItem('ev_geo',JSON.stringify(geo));}catch(e){} cb(geo); } }// Cloudflare trace — country
fetch('/cdn-cgi/trace', {cache:'no-store'})
.then(function(r){ return r.text(); })
.then(function(txt){
var m = txt.match(/loc=([A-Z]{2})/);
if (m) geo.geo_country = m[1];
done();
})
.catch(done);// ipapi.co — city/region/zip (60 req/min free, no key)
fetch('https://ipapi.co/json/', {cache:'no-store'})
.then(function(r){ return r.ok ? r.json() : null; })
.then(function(j){
if (j) {
geo.geo_city = j.city || '';
geo.geo_region = j.region || '';
geo.geo_zip = j.postal || '';
if (!geo.geo_country) geo.geo_country = j.country_code || '';
}
done();
})
.catch(done);
}// ---------- 5. Populate run ----------
function runPopulate(){
var data = firstTouchMerge(readUrlParams());
setAll(data);
setAll(pageContext());loadGeo(function(geo){
setAll(geo);
});
}// ---------- 6. Hook into Avada submit (final safety net) ----------
// Avada Forms emit "submit" on the