Free Consultation
HARLECH ECRU OAK
HARLECH ECRU OAK

HARLECH ECRU OAK

Harlech | woodpecker

woodpecker Logo
plank Logoherringbone Logo

From: £98 per m²

This pale floor is the perfect complement to modern interiors. Boards have an unfinished look and brushed texture for a beautifully natural feel. Harlech Ecru Oak is also available in a matching herringbone plank (Goodrich Ecru Oak).

Visit our showroom

Our website is a non-exhaustive snapshot of the products we offer.

So, before you make any big decisions, visit our showroom and see the full range in real life, ask our experts a question and get a free consultation.

(function () { // --- CONFIG --- // UTM / tracking keys you want to capture & persist var KEYS = [ 'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'utm_id', 'gclid', 'fbclid', 'li_fat_id' ]; // Session logic (30 mins) var SESSION_PREFIX = 'utm_session_'; var FIRST_PREFIX = 'utm_first_'; var SESSION_STARTED_KEY = 'utm_session_started_at'; var SESSION_TTL_MS = 30 * 60 * 1000; // 30 minutes // --- HELPERS --- function now() { return (new Date()).getTime(); } function getUrlParams() { var params = {}; var query = window.location.search || ''; if (query.charAt(0) === '?') query = query.substring(1); if (!query) return params; query.split('&').forEach(function (pair) { if (!pair) return; var parts = pair.split('='); var key = decodeURIComponent(parts[0] || '').trim(); var val = decodeURIComponent(parts[1] || '').trim(); if (key) params[key] = val; }); return params; } function appendQuery(url, qs) { if (!qs) return url; // Don't double-append if already there if (url.indexOf('utm_source=') !== -1 || url.indexOf('utm_medium=') !== -1 || url.indexOf('utm_campaign=') !== -1) { return url; } var hash = ''; var base = url; // keep hash fragment at the end var hashIndex = url.indexOf('#'); if (hashIndex !== -1) { base = url.substring(0, hashIndex); hash = url.substring(hashIndex); } base += (base.indexOf('?') === -1 ? '?' : '&') + qs; return base + hash; } function buildQueryFromSession() { var parts = []; KEYS.forEach(function (key) { var val = null; try { val = window.sessionStorage.getItem(SESSION_PREFIX + key); } catch (e) {} if (val) { parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(val)); } }); return parts.join('&'); } function safeSet(storage, key, value) { try { if (value) storage.setItem(key, value); } catch (e) {} } function safeGet(storage, key) { try { return storage.getItem(key); } catch (e) { return null; } } // --- STEP 1: READ UTM PARAMS FROM URL --- var urlParams = getUrlParams(); var hasNew = KEYS.some(function (k) { return !!urlParams[k]; }); var sessionStartedAt = parseInt(safeGet(window.sessionStorage, SESSION_STARTED_KEY) || '0', 10); var sessionExpired = !sessionStartedAt || (now() - sessionStartedAt > SESSION_TTL_MS); // --- STEP 2: UPDATE SESSION & FIRST-TOUCH STORAGE --- if (hasNew || sessionExpired) { safeSet(window.sessionStorage, SESSION_STARTED_KEY, String(now())); KEYS.forEach(function (key) { if (urlParams[key]) { // Current session values safeSet(window.sessionStorage, SESSION_PREFIX + key, urlParams[key]); // First-touch values (only set once) var existingFirst = safeGet(window.localStorage, FIRST_PREFIX + key); if (!existingFirst) { safeSet(window.localStorage, FIRST_PREFIX + key, urlParams[key]); } } }); } // If no session values yet, hydrate from first-touch (localStorage) KEYS.forEach(function (key) { var sessVal = safeGet(window.sessionStorage, SESSION_PREFIX + key); if (!sessVal) { var firstVal = safeGet(window.localStorage, FIRST_PREFIX + key); if (firstVal) { safeSet(window.sessionStorage, SESSION_PREFIX + key, firstVal); } } }); // --- STEP 3: PUSH INTO dataLayer FOR GTM / GA4 --- (function pushToDataLayer() { var utmData = {}; KEYS.forEach(function (key) { var val = safeGet(window.sessionStorage, SESSION_PREFIX + key); if (val) { utmData[key] = val; } }); if (Object.keys(utmData).length > 0) { utmData.event = 'utm_ready'; window.dataLayer = window.dataLayer || []; window.dataLayer.push(utmData); } })(); // --- STEP 4: PASS UTM TO TYPEFORM (IFRAMES & LINKS) --- function updateTypeforms() { var qs = buildQueryFromSession(); if (!qs) return; // a) Embedded Typeform iframes var iframes = document.querySelectorAll('iframe[src*="typeform.com"]'); Array.prototype.forEach.call(iframes, function (iframe) { var src = iframe.getAttribute('src'); if (src) { var newSrc = appendQuery(src, qs); if (newSrc !== src) { iframe.setAttribute('src', newSrc); } } }); // b) Links to Typeform var links = document.querySelectorAll('a[href*="typeform.com"]'); Array.prototype.forEach.call(links, function (a) { var href = a.getAttribute('href'); if (href) { var newHref = appendQuery(href, qs); if (newHref !== href) { a.setAttribute('href', newHref); } } }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', updateTypeforms); } else { updateTypeforms(); } })();