Landing Page Form

Looking to get your home professionally washed?

Mother's Day Special — 10% off a house wash · 30% off additional services.

Free estimate Local & insured 5-star rated
Free Estimate · 60 sec

Where should we send your estimate?

Takes about 60 seconds.

Please fill in your name and phone number.
Almost done

What needs to be cleaned?

Bundle add-ons with a house wash for 30% off.

Please select at least one service.
Free estimates
No obligation
Local & insured
5-star rated

Thank you 🙏

We received your job details.

Just a few quick questions to get your estimate right.

LP Pressure Wash — Estimator
Online now
Tap again
Powered by LP Pressure Wash AI Estimator
' + t + '
'; msgs.appendChild(d); msgs.appendChild(typing); msgs.scrollTop = msgs.scrollHeight; } function esc(s) { return s.replace(/&/g, '&').replace(//g, '>'); } // Render a row of clickable pill buttons under the most recent bot bubble. // Tapping one fires it as the user's reply via the existing chat flow. // After any pill in the row is tapped, the whole row disables (no double-tap). function addQuickReplies(options) { if (!Array.isArray(options) || !options.length) return; // Disable any older quick-reply rows so only the latest is interactive document.querySelectorAll('#chatMsgs .lp-qr-wrap').forEach(w => { w.querySelectorAll('button').forEach(b => b.disabled = true); }); const msgs = document.getElementById('chatMsgs'); const typing = document.getElementById('typing'); const wrap = document.createElement('div'); wrap.className = 'lp-qr-wrap'; options.forEach(opt => { const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'lp-qr-btn'; btn.textContent = opt; btn.onclick = function () { // Disable all buttons in this row immediately wrap.querySelectorAll('button').forEach(b => b.disabled = true); const inp = document.getElementById('chatInp'); if (inp) { inp.value = opt; window.lpSend(); } }; wrap.appendChild(btn); }); msgs.insertBefore(wrap, typing); msgs.scrollTop = msgs.scrollHeight; } window.lpGrow = function (el) { el.style.height = 'auto'; el.style.height = Math.min(el.scrollHeight, 120) + 'px'; }; async function callEstimate(userText) { const typing = document.getElementById('typing'); typing.classList.add('show'); document.getElementById('chatMsgs').scrollTop = 1e9; if (userText) history.push({ role: 'user', content: userText }); try { const res = await fetch(ESTIMATE_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ messages: history, formData: fd, clientId, jobId, attribution }) }); const data = await res.json(); typing.classList.remove('show'); if (data.reply) { history.push({ role: 'assistant', content: data.reply }); addBubble(data.reply, 'bot'); } if (Array.isArray(data.quickReplies) && data.quickReplies.length) addQuickReplies(data.quickReplies); if (data.clientId) clientId = data.clientId; if (data.jobId) jobId = data.jobId; saveState(); } catch (err) { typing.classList.remove('show'); addBubble("Sorry, something went wrong. Reach us directly at (267) 912-8285 📱", 'bot'); console.error(err); } } window.lpSend = async function () { if (sending) return; const inp = document.getElementById('chatInp'); const btn = document.getElementById('sendBtn'); const text = inp.value.trim(); if (!text) return; sending = true; btn.disabled = true; inp.value = ''; window.lpGrow(inp); addBubble(text, 'usr'); await callEstimate(text); sending = false; btn.disabled = false; inp.focus(); }; window.lpKey = function (e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); window.lpSend(); } }; // ── Restart button (two-tap confirm) ───────────────────────────────────── // Airtable data already collected stays in Airtable — this only clears the // local widget so the customer can start a new chat. let restartArmed = false; let restartTimer = null; window.lpRestartTap = function () { const btn = document.getElementById('lpRestartBtn'); const text = document.getElementById('lpRestartText'); if (restartArmed) { if (restartTimer) clearTimeout(restartTimer); doRestart(); return; } restartArmed = true; btn && btn.classList.add('armed'); if (text) text.style.display = ''; restartTimer = setTimeout(() => { restartArmed = false; btn && btn.classList.remove('armed'); if (text) text.style.display = 'none'; }, 3000); }; function doRestart() { restartArmed = false; const btn = document.getElementById('lpRestartBtn'); const text = document.getElementById('lpRestartText'); btn && btn.classList.remove('armed'); if (text) text.style.display = 'none'; clearState(); fd.services = []; fd.condition = ''; fd.firstName = ''; fd.phone = ''; fd.address = ''; fd.notes = ''; history.length = 0; clientId = null; jobId = null; sending = false; pendingFirstResponse = null; currentStep = 1; currentPhase = 'form'; document.querySelectorAll('#lpWrap .lp-pick.sel').forEach(el => el.classList.remove('sel')); const n = document.getElementById('iName'); const p = document.getElementById('iPhone'); const a = document.getElementById('iAddr'); const nt = document.getElementById('iNotes'); if (n) n.value = ''; if (p) p.value = ''; if (a) a.value = ''; if (nt) nt.value = ''; ['e1','e2'].forEach(hideErr); const formEl = document.getElementById('lpForm'); const transEl = document.getElementById('lpTransition'); const chatEl = document.getElementById('lpChat'); const heroEl = document.getElementById('lpHero'); formEl.style.display = 'none'; formEl.classList.remove('hide'); transEl.classList.remove('active'); transEl.style.display = ''; ['tl1','tl2','tl3'].forEach(id => document.getElementById(id)?.classList.remove('show')); chatEl.classList.remove('active'); // Bring the hero back so the user lands on the marketing screen, not a blank form if (heroEl) { heroEl.classList.add('active'); heroEl.style.display = ''; } lpCloseModal(); const msgs = document.getElementById('chatMsgs'); const typing = document.getElementById('typing'); if (msgs && typing) { Array.from(msgs.children).forEach(c => { if (c !== typing) msgs.removeChild(c); }); typing.classList.remove('show'); } const chatInp = document.getElementById('chatInp'); if (chatInp) { chatInp.value = ''; window.lpGrow(chatInp); } currentPhase = 'hero'; setStep(1); } // ── Hero CTA: open the form modal on top of the hero ───────────────────── // Hero stays visible underneath. Modal closes on X / backdrop click / ESC, // or auto-closes on submit before the transition + chat phase takes over. window.lpStartFromHero = function () { const modal = document.getElementById('lpModalRoot'); const form = document.getElementById('lpForm'); if (!modal || !form) return; form.style.display = ''; modal.classList.add('active'); // Lock background scroll so the modal feels like a popup document.body.style.overflow = 'hidden'; if (currentPhase !== 'chat' && currentPhase !== 'transition') currentPhase = 'form'; setStep(currentStep || 1); saveState(); // Focus the first empty contact field for fast typing setTimeout(() => { const firstEmpty = ['iName','iPhone','iEmail','iAddr'] .map(id => document.getElementById(id)) .find(el => el && !el.value); if (firstEmpty) firstEmpty.focus(); }, 250); }; window.lpCloseModal = function () { const modal = document.getElementById('lpModalRoot'); if (!modal) return; modal.classList.remove('active'); document.body.style.overflow = ''; }; // Click outside the form card → close modal (function bindModalDismiss() { const modal = document.getElementById('lpModalRoot'); if (modal) { modal.addEventListener('click', function (e) { if (e.target === modal) lpCloseModal(); }); } document.addEventListener('keydown', function (e) { if (e.key === 'Escape' && modal && modal.classList.contains('active')) lpCloseModal(); }); })(); // ── Restore state on load if we have a recent session ──────────────────── function restoreFromSaved() { const saved = loadState(); try { console.log('[lpWidget] restoreFromSaved →', saved ? { step: saved.currentStep, phase: saved.currentPhase, hasName: !!saved.fd?.firstName } : 'no saved state'); } catch {} if (!saved) return; // no saved state → leave hero visible (default) Object.assign(fd, saved.fd || {}); currentStep = saved.currentStep || 1; if (currentStep > 2) currentStep = 2; // clamp — form is now 2 steps currentPhase = saved.currentPhase || 'form'; if (Array.isArray(saved.history)) { history.length = 0; history.push.apply(history, saved.history); } clientId = saved.clientId || null; jobId = saved.jobId || null; // Re-tick service cards (now on step 2) document.querySelectorAll('#lpS2 .lp-pick').forEach(btn => { if ((fd.services || []).indexOf(btn.dataset.val) > -1) btn.classList.add('sel'); }); // Re-fill contact inputs (step 1) and the optional notes textarea (step 2) const nameEl = document.getElementById('iName'); const phoneEl = document.getElementById('iPhone'); const emailEl = document.getElementById('iEmail'); const addrEl = document.getElementById('iAddr'); const notesEl = document.getElementById('iNotes'); if (nameEl) nameEl.value = fd.firstName || ''; if (phoneEl) phoneEl.value = fd.phone || ''; if (emailEl) emailEl.value = fd.email || ''; if (addrEl) addrEl.value = fd.address || ''; if (notesEl) notesEl.value = fd.notes || ''; if (currentPhase === 'chat') { // User finished the form earlier — drop the hero, show chat directly. const heroEl = document.getElementById('lpHero'); if (heroEl) { heroEl.classList.remove('active'); heroEl.style.display = 'none'; } document.getElementById('lpForm').style.display = 'none'; document.getElementById('lpTransition').style.display = 'none'; document.getElementById('lpChat').classList.add('active'); const msgs = document.getElementById('chatMsgs'); const typing = document.getElementById('typing'); history.forEach(m => { const d = document.createElement('div'); d.className = 'msg ' + (m.role === 'user' ? 'usr' : 'bot'); d.innerHTML = '
' + esc(m.content || '') + '
'; msgs.insertBefore(d, typing); }); msgs.scrollTop = msgs.scrollHeight; } else if (currentPhase === 'transition') { // User hit submit, page reloaded before chat opened — jump straight to chat. currentPhase = 'chat'; const heroEl = document.getElementById('lpHero'); if (heroEl) { heroEl.classList.remove('active'); heroEl.style.display = 'none'; } document.getElementById('lpForm').style.display = 'none'; document.getElementById('lpChat').classList.add('active'); document.getElementById('typing').classList.add('show'); callEstimate(''); } else { // Mid-form on a fresh page load: hero stays visible, modal is closed. // User clicks the CTA again to resume — fields are already pre-filled // from the assignments above. setStep just preps the right tab. setStep(currentStep); } } // Manual reset (useful for debugging: call lpReset() in console) window.lpReset = function () { clearState(); location.reload(); }; restoreFromSaved(); })();
5 months ago
Luke did a great job cleaning our siding, deck, and all the hardscape around our home. Pricing was easy and fair, he showed up on time and completed the job with a great deal of care and attention to detail. We will definitely use him again the next time we need pressure washing done.
6 months ago
Luke done a fantastic job, we are really happy!!!. He power washed our house, deck and fence, now these looks great. The price was reasonable. I recommend his services!
a year ago
Just an awesome job on my home. Siding and pavers look incredible. They look brand new again. Very easy to work with, reasonable, and just an amazing job. Siding is perfect and I cannot believe how great these came out. The before and after is unbelievable. Just a great experience working with them.

FAQ

Yes, we carry liability insurance so that anything that would happen to your property is covered. In 7 years, we haven’t had to use it yet.

Most surfaces we do soft washing. Soft washing uses water pressure weak enough that you can put your hand in front of the stream. It relies on a heavily diluted bleach based solution to clean the algae and mildew. We dilute to around 1:8 (chemical:water) to 1:20 depending on the grime and surface. 

No, we water before and after use. Our solution is heavily diluted with water. We can cover more delicate flowers if they are directly under or next to the cleaning area. 

For wood, composite, treks, pvc, vinyl decks we use a surface cleaner which a is circular high-pressure method that creates a smooth finish. We follow the board lines. We soap before using the surface cleaner. The edges, spindles, or stairs are cleaned with the wand. The key is moving at the correct pace, with long smooth strokes. 

Rarely, we can reach most peaks from the ground. For gutter cleaning (inside) we will. Sometimes we will need to set up a ladder to reach over the first story that hangs out to reach the second story. 

We price per job, not time. We will give you an estimate and that won’t change unless you want to add a service. Small things like a bench or window we can do out of courtesy ofc. You pay after. We accept checks, Venmo, Zelle, Cash App. 

No, as long as the water is on and the windows are closed, we are good to go. Takes around 4-10 hours depending on the job. 

Soft washing lasts longer than just using pressure… we see this a lot from past clients. Usually, your siding will stay clean for 2-3 years. The north facing side possible will take only a year. We do some homes once a year though.

Typically, within 1 hour of Quakertown which covers lower Leigh Valley, Bucks, and most of Montgomery County. Every year we do some jobs at the NJ coast, so we can accommodate. 

About us

We’ve been cleaning homes for over 7 years

Two brothers offer pressure washing, soft washing, and other exterior services to residents throughout Bucks County, Montgomery County, and Lehigh County. 

At LP Pressure Washing, we value our clients and want to build a long-lasting relationship based on trust and reliability. Customer satisfaction and fulfilling your needs is our primary goal. We know that your home and property are important- that is why it is our number one priority to protect it, do a high-quality job, and restore it to looking its very best again.

Projects

Look at our results