Author SHA1 Message Date
oliver a54dc22bd1 copy(footer): say "AI Agents and N8N automations" in the About-us blurb
Updates the homepage footer tagline to name AI Agents and N8N
automations explicitly. Markup-preserving: existing <strong> emphasis
on "stability" and "power" is unchanged; no structural, style or
layout changes.
2026-10-20 13:09:31 +00:00
oliver ca89d8e7b7 confirm 2026-10-17 17:10:09 -03:00
oliver 29127d4025 chat fixes 2026-10-17 10:50:45 -03:00
oliver b4e0faa62e UTM 2026-10-17 10:40:05 -03:00
oliver 575e3efece Update upsell.html 2026-10-17 09:39:08 -03:00
oliver 62f92769a1 Update upsell.html 2026-10-17 09:30:55 -03:00
oliver 3637094896 url 2026-10-16 08:42:42 -03:00
oliver 609f9d64bf new produt id 2026-10-16 08:39:01 -03:00
oliver 1ab6c47df6 Update index.html 2026-10-16 08:29:29 -03:00
Reef 354799b9ca fix: repair contact flow and buy flow targets
- Buy Now product IDs aligned to the Odoo shop (54/55/56), matching odoo/upsell.html
- support.html contact form: rewire from dead ODOO4projects.com/website/form endpoint to n8n CRM webhook; remove /web/csrf_token prefetch; show success only on res.ok (previously always showed 'submitted' even when nothing was delivered)
- /contactus links (footer nav, Schema contactPoint, order widget fallback, trial email) retargeted to support.html#contact; canonical/og:url corrected to /support.html
- Custom Quote and footer contact handlers hardened with res.ok checks
- buyNow basket target verified: 20.odoo4projects.com/shop/post_basket (200)
2026-10-12 15:41:11 +00:00
7 changed files with 157 additions and 46 deletions

No files matched your search

+1 -1
View File
@@ -24,7 +24,7 @@ Enterprise-grade Odoo Community hosting without the enterprise price tag. Commun
- Static site (index.html, support.html, legal.html, blog/) deployed via git push to git.odoo4projects.com; auto-deploys on every change. - Static site (index.html, support.html, legal.html, blog/) deployed via git push to git.odoo4projects.com; auto-deploys on every change.
- Order flow: inline order widget on the homepage opens Stripe checkout; coupon FREE TRIAL = 1 month free; yearly billing saves roughly 8-10%; "Satisfied or reimbursed" guarantee; server location chosen at checkout (US, Brazil, India, Australia, Netherlands, UK). - Order flow: inline order widget on the homepage opens Stripe checkout; coupon FREE TRIAL = 1 month free; yearly billing saves roughly 8-10%; "Satisfied or reimbursed" guarantee; server location chosen at checkout (US, Brazil, India, Australia, Netherlands, UK).
- Support: AI support bot (agent.js from static.odoo4projects.com) plus human team; email support@odoo4projects.com; /contactus route. - Support: AI support bot (agent.js from static.odoo4projects.com) plus human team; email support@odoo4projects.com; contact form on support.html#contact.
- Blog with guides and news (10 posts); homepage renders it with search and pagination. - Blog with guides and news (10 posts); homepage renders it with search and pagination.
## Capabilities and Constraints ## Capabilities and Constraints
+1 -1
View File
@@ -190,7 +190,7 @@
<p> <p>
<a href="https://odoo4projects.com/legal/privacy">Privacy</a> &bull; <a href="https://odoo4projects.com/legal/privacy">Privacy</a> &bull;
<a href="https://odoo4projects.com/legal/terms">Terms</a> &bull; <a href="https://odoo4projects.com/legal/terms">Terms</a> &bull;
<a href="https://odoo4projects.com/contactus">Contact</a> <a href="https://ODOO4projects.com/support.html#contact">Contact</a>
</p> </p>
<p class="unsubscribe"> <p class="unsubscribe">
<a href="https://odoo4projects.com/unsubscribe?token=USER_TOKEN">Unsubscribe</a> from these emails <a href="https://odoo4projects.com/unsubscribe?token=USER_TOKEN">Unsubscribe</a> from these emails
+17 -5
View File
@@ -20,7 +20,7 @@
"url": "https://ODOO4projects.com/", "url": "https://ODOO4projects.com/",
"description": "Odoo hosting with fully managed infrastructure. Deploy in 5 minutes with automatic backups, SSL, and Git-based modules.", "description": "Odoo hosting with fully managed infrastructure. Deploy in 5 minutes with automatic backups, SSL, and Git-based modules.",
"foundingDate": "2020", "foundingDate": "2020",
"contactPoint": { "@type": "ContactPoint", "contactType": "customer support", "url": "https://ODOO4projects.com/contactus" }, "contactPoint": { "@type": "ContactPoint", "contactType": "customer support", "url": "https://ODOO4projects.com/support.html#contact" },
"sameAs": ["https://www.linkedin.com/company/odoo4projects/"], "sameAs": ["https://www.linkedin.com/company/odoo4projects/"],
"offers": [ "offers": [
{ "@type": "Offer", "name": "Side Hustle", "price": "214.00", "priceCurrency": "USD", "url": "https://ODOO4projects.com/#pricing" }, { "@type": "Offer", "name": "Side Hustle", "price": "214.00", "priceCurrency": "USD", "url": "https://ODOO4projects.com/#pricing" },
@@ -117,6 +117,13 @@
.hero-sub{font-size:1.05rem;color:rgba(255,255,255,.7);max-width:560px;line-height:1.7;margin-bottom:1.5rem} .hero-sub{font-size:1.05rem;color:rgba(255,255,255,.7);max-width:560px;line-height:1.7;margin-bottom:1.5rem}
.hero-stats{display:flex;gap:1.5rem;margin-bottom:2rem;flex-wrap:wrap}.hero-stat{display:flex;align-items:center;gap:.4rem;color:rgba(255,255,255,.65);font-size:.85rem}.hero-stat i{color:var(--brass);font-size:.75rem} .hero-stats{display:flex;gap:1.5rem;margin-bottom:2rem;flex-wrap:wrap}.hero-stat{display:flex;align-items:center;gap:.4rem;color:rgba(255,255,255,.65);font-size:.85rem}.hero-stat i{color:var(--brass);font-size:.75rem}
.hero-actions{display:flex;gap:1rem;flex-wrap:wrap;margin-bottom:2rem} .hero-actions{display:flex;gap:1rem;flex-wrap:wrap;margin-bottom:2rem}
.hero-notice{position:absolute;top:1.25rem;right:1.25rem;z-index:3;display:flex;align-items:center;gap:.55rem;max-width:min(360px,calc(100% - 2rem));padding:.6rem .85rem .6rem 1rem;background:#f5c542;color:var(--midnight);border:1px solid rgba(13,27,46,.14);border-radius:var(--radius);box-shadow:0 8px 24px rgba(13,27,46,.3);font-family:Inter,sans-serif;font-size:.82rem;line-height:1.4;animation:heroNoticeIn .4s cubic-bezier(.16,1,.3,1)}
.hero-notice[hidden]{display:none}
.hero-notice i{color:var(--midnight);font-size:.9rem;flex-shrink:0}
.hero-notice-text{flex:1;min-width:0;overflow-wrap:anywhere}
.hero-notice-close{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:1.35rem;height:1.35rem;padding:0;border:0;border-radius:50%;background:rgba(13,27,46,.12);color:var(--midnight);font-size:1rem;line-height:1;cursor:pointer;transition:background .2s}
.hero-notice-close:hover{background:rgba(13,27,46,.24)}
@keyframes heroNoticeIn{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
.server-banner{background:var(--midnight);padding:2rem 0 1.5rem;border-top:1px solid var(--line-brass);border-bottom:1px solid var(--line-brass);position:relative;overflow:hidden} .server-banner{background:var(--midnight);padding:2rem 0 1.5rem;border-top:1px solid var(--line-brass);border-bottom:1px solid var(--line-brass);position:relative;overflow:hidden}
.server-banner::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse 60% 80% at 50% 100%,rgba(201,162,39,.06) 0%,transparent 70%);pointer-events:none} .server-banner::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse 60% 80% at 50% 100%,rgba(201,162,39,.06) 0%,transparent 70%);pointer-events:none}
.server-banner-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.25rem;flex-wrap:wrap;gap:.5rem} .server-banner-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.25rem;flex-wrap:wrap;gap:.5rem}
@@ -138,7 +145,7 @@
.pricing-server-select{padding:.5rem 1rem;border-radius:var(--radius);border:1px solid var(--line-brass);background:rgba(255,255,255,.08);color:#fff;font-family:Inter,sans-serif;font-size:.85rem;outline:none;cursor:pointer;min-width:180px} .pricing-server-select{padding:.5rem 1rem;border-radius:var(--radius);border:1px solid var(--line-brass);background:rgba(255,255,255,.08);color:#fff;font-family:Inter,sans-serif;font-size:.85rem;outline:none;cursor:pointer;min-width:180px}
.pricing-server-select option{background:var(--midnight);color:#fff} .pricing-server-select option{background:var(--midnight);color:#fff}
@media(max-width:992px){.server-grid{grid-template-columns:repeat(3,1fr)}} @media(max-width:992px){.server-grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:768px){.hero{min-height:auto;padding:3rem 0 0}.hero-actions{flex-direction:column}.hero-actions .btn{width:100%;text-align:center}.hero-stats{gap:.75rem}.hero-city-label{bottom:1rem;right:1rem;font-size:.78rem;padding:.5rem .9rem}} @media(max-width:768px){.hero{min-height:auto;padding:3rem 0 0}.hero.has-hero-notice{padding-top:4.75rem}.hero-actions{flex-direction:column}.hero-actions .btn{width:100%;text-align:center}.hero-stats{gap:.75rem}.hero-city-label{bottom:1rem;right:1rem;font-size:.78rem;padding:.5rem .9rem}.hero-notice{top:.75rem;left:.75rem;right:.75rem;max-width:none;font-size:.78rem}}
@media(max-width:576px){.server-grid{grid-template-columns:repeat(2,1fr)}.server-banner-header{flex-direction:column;align-items:flex-start}} @media(max-width:576px){.server-grid{grid-template-columns:repeat(2,1fr)}.server-banner-header{flex-direction:column;align-items:flex-start}}
.status-dot{width:7px;height:7px;border-radius:50%;background:var(--brass);display:inline-block;animation:statusPulse 1.2s ease-in-out infinite} .status-dot{width:7px;height:7px;border-radius:50%;background:var(--brass);display:inline-block;animation:statusPulse 1.2s ease-in-out infinite}
@keyframes statusPulse{0%,100%{opacity:.3;transform:scale(.8)}50%{opacity:1;transform:scale(1.2)}} @keyframes statusPulse{0%,100%{opacity:.3;transform:scale(.8)}50%{opacity:1;transform:scale(1.2)}}
@@ -217,6 +224,11 @@
--> -->
<!-- Hero --> <!-- Hero -->
<section class="hero"> <section class="hero">
<div class="hero-notice" id="heroConfirmNotice" role="status" aria-live="polite" hidden>
<i class="fas fa-check-circle" aria-hidden="true"></i>
<span class="hero-notice-text"></span>
<button type="button" class="hero-notice-close" aria-label="Dismiss notification">&times;</button>
</div>
<div class="container"> <div class="container">
<div class="hero-kicker">Fully Managed Odoo Community Hosting</div> <div class="hero-kicker">Fully Managed Odoo Community Hosting</div>
<h1>Deploy Odoo in <span>5 Minutes</span> — Fully Managed Hosting</h1> <h1>Deploy Odoo in <span>5 Minutes</span> — Fully Managed Hosting</h1>
@@ -489,7 +501,7 @@
</div> </div>
<p class="ow-coupon-status" id="orderCouponStatus">&#10003; Coupon applied</p> <p class="ow-coupon-status" id="orderCouponStatus">&#10003; Coupon applied</p>
</div> </div>
<a id="orderBuyBtn" href="/contactus" class="btn btn-brass ow-buy">Continue to Stripe &rarr;</a> <a id="orderBuyBtn" href="/support.html#contact" class="btn btn-brass ow-buy">Continue to Stripe &rarr;</a>
<p class="ow-note">&#128274; Secure Stripe checkout &middot; Credit card required</p> <p class="ow-note">&#128274; Secure Stripe checkout &middot; Credit card required</p>
</div> </div>
</div> </div>
@@ -614,7 +626,7 @@
<li><a href="index.html">Home</a></li> <li><a href="index.html">Home</a></li>
<li><a href="support.html">Support</a></li> <li><a href="support.html">Support</a></li>
<li><a href="legal.html">Legal</a></li> <li><a href="legal.html">Legal</a></li>
<li><a href="/contactus">Contact us</a></li> <li><a href="/support.html#contact">Contact us</a></li>
</ul> </ul>
</div> </div>
<div> <div>
@@ -627,7 +639,7 @@
</div> </div>
<div class="fcol-desc"> <div class="fcol-desc">
<h4>About us</h4> <h4>About us</h4>
<p>We build smart, scalable business solutions by combining the <strong>stability</strong> of Odoo ERP with the <strong>power</strong> of AI and N8N automation.</p> <p>We build smart, scalable business solutions by combining the <strong>stability</strong> of Odoo ERP with the <strong>power</strong> of AI Agents and N8N automations.</p>
<p>From streamlined sales to global rollouts, our <strong>lean, eco-friendly</strong> approach helps businesses cut costs, boost efficiency, and grow without limits.</p> <p>From streamlined sales to global rollouts, our <strong>lean, eco-friendly</strong> approach helps businesses cut costs, boost efficiency, and grow without limits.</p>
</div> </div>
<div> <div>
+9 -13
View File
@@ -20,7 +20,7 @@
*{box-sizing:border-box} *{box-sizing:border-box}
body{margin:0;background:linear-gradient(180deg,var(--bg),#eef2f8);min-height:100vh;display:flex;align-items:center;justify-content:center;padding:28px} body{margin:0;background:linear-gradient(180deg,var(--bg),#eef2f8);min-height:100vh;display:flex;align-items:center;justify-content:center;padding:28px}
.app{width:960px;max-width:96vw;background:transparent;display:grid;grid-template-columns:320px 1fr;gap:20px} .app{width:1146px;max-width:96vw;background:transparent;display:grid;grid-template-columns:320px 1fr;gap:20px;align-items:stretch}
/* Left column - user list / details */ /* Left column - user list / details */
.sidebar{background:linear-gradient(180deg,rgba(255,255,255,0.9),var(--card));border-radius:var(--radius);padding:20px;box-shadow:0 6px 20px rgba(24,39,75,0.06);overflow:hidden} .sidebar{background:linear-gradient(180deg,rgba(255,255,255,0.9),var(--card));border-radius:var(--radius);padding:20px;box-shadow:0 6px 20px rgba(24,39,75,0.06);overflow:hidden}
@@ -55,17 +55,16 @@
.sidebar .hint{margin-top:14px;padding:10px;border-radius:10px;background:#fbf8ff;color:#5b4160;font-size:13px} .sidebar .hint{margin-top:14px;padding:10px;border-radius:10px;background:#fbf8ff;color:#5b4160;font-size:13px}
/* Chat area */ /* Chat area */
.chat-card{background:var(--card);border-radius:var(--radius);display:flex;flex-direction:column;height:70vh;box-shadow:0 10px 30px rgba(24,39,75,0.06);overflow:hidden} .chat-card{background:var(--card);border-radius:var(--radius);display:flex;flex-direction:column;height:100%;min-height:0;box-shadow:0 10px 30px rgba(24,39,75,0.06);overflow:hidden}
.chat-header{display:flex;align-items:center;gap:12px;padding:18px;border-bottom:1px solid #eef1f6} .chat-header{display:flex;align-items:center;gap:12px;padding:18px;border-bottom:1px solid #eef1f6}
.chat-header .title{font-weight:600;color:var(--odoo-dark)} .chat-header .title{font-weight:600;color:var(--odoo-dark)}
.chat-header .sub{font-size:13px;color:var(--muted)} .chat-header .sub{font-size:13px;color:var(--muted)}
.messages{flex:1;padding:22px;overflow:auto;background:linear-gradient(180deg,#fbfcff, #f7f9fc)} .messages{flex:1;min-height:0;padding:22px;overflow:auto;background:linear-gradient(180deg,#fbfcff, #f7f9fc)}
.messages-inner{max-width:760px;margin:0 auto;display:flex;flex-direction:column;gap:12px} .messages-inner{max-width:760px;margin:0 auto;display:flex;flex-direction:column;gap:12px}
.msg{display:flex;gap:10px;align-items:flex-end} .msg{display:flex;gap:10px;align-items:flex-end;width:100%}
.msg.me{justify-content:flex-end} .bubble{width:100%;max-width:100%;padding:12px 14px;border-radius:12px;background:white;border:1px solid #eef1f6;font-size:14px;color:#222}
.bubble{max-width:68%;padding:12px 14px;border-radius:12px;background:white;border:1px solid #eef1f6;font-size:14px;color:#222}
.bubble.me{background:linear-gradient(90deg,var(--odoo-purple),#9b6fa0);color:white;border:none} .bubble.me{background:linear-gradient(90deg,var(--odoo-purple),#9b6fa0);color:white;border:none}
.meta-time{font-size:11px;color:var(--muted);margin-top:6px} .meta-time{font-size:11px;color:var(--muted);margin-top:6px}
@@ -204,16 +203,13 @@ Please note: it does not cover general Odoo usage or functional questions.
const col = document.createElement('div'); const col = document.createElement('div');
col.style.display = 'flex'; col.style.display = 'flex';
col.style.flexDirection = 'column'; col.style.flexDirection = 'column';
col.style.flex = '1';
col.style.minWidth = '0';
col.appendChild(bubble); col.appendChild(bubble);
col.appendChild(meta); col.appendChild(meta);
if(who==='me'){ wrap.appendChild(avatar);
wrap.appendChild(col); wrap.appendChild(col);
wrap.appendChild(avatar);
} else {
wrap.appendChild(avatar);
wrap.appendChild(col);
}
messagesEl.appendChild(wrap); messagesEl.appendChild(wrap);
messagesEl.parentElement.scrollTop = messagesEl.parentElement.scrollHeight; messagesEl.parentElement.scrollTop = messagesEl.parentElement.scrollHeight;
+48 -9
View File
@@ -297,7 +297,7 @@
<script> <script>
// ── Webhooks ───────────────────────────────────────────────────────────── // ── Webhooks ─────────────────────────────────────────────────────────────
const getContract_Webhook = const getContract_Webhook =
"https://002-001-5dd6e535-4d1c-46bc-9bd9-42ad4bc5f082.odoo4projects.com/webhook/0c8536be-d175-4740-8e78-123159193b23"; "https://n8n.odoo4projects.com/webhook/ODOO4projects/upsell";
// ── Plan hierarchy (index = tier, lower = cheaper) ──────────────────────── // ── Plan hierarchy (index = tier, lower = cheaper) ────────────────────────
const PLAN_ORDER = [ const PLAN_ORDER = [
@@ -337,11 +337,46 @@
// ── Product ID mapping ───────────────────────────────────────── // ── Product ID mapping ─────────────────────────────────────────
const PRODUCT_IDS = { const PRODUCT_IDS = {
sidehustle: 54, sidehustle: 6,
ontherise: 55, ontherise: 4,
powerhouse: 56, powerhouse: 5,
}; };
// ── UTM tracking (source / medium / campaign) ─────────────────────────────
const UTM_KEYS = ["source", "medium", "campaign"];
function getCookie(name) {
const match = document.cookie.match(new RegExp("(^| )" + name + "=([^;]+)"));
return match ? decodeURIComponent(match[2]) : null;
}
function setCookie(name, value, days) {
const date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
document.cookie =
name + "=" + encodeURIComponent(value) +
"; expires=" + date.toUTCString() +
"; path=/; SameSite=Lax";
}
UTM_KEYS.forEach(function (key) {
const val = params.get("utm_" + key);
if (val) setCookie("utm_" + key, val, 90);
});
function appendUTM(form) {
UTM_KEYS.forEach(function (key) {
const val = getCookie("utm_" + key);
if (val) {
const input = document.createElement("input");
input.type = "hidden";
input.name = "utm_" + key;
input.value = val;
form.appendChild(input);
}
});
}
// ── Buy handler ─────────────────────────────────────────────────────────── // ── Buy handler ───────────────────────────────────────────────────────────
function buyProduct(productId) { function buyProduct(productId) {
if (!uuid) { if (!uuid) {
@@ -355,7 +390,7 @@
} }
var form = document.createElement("form"); var form = document.createElement("form");
form.method = "POST"; form.method = "POST";
form.action = window.location.origin + "/shop/post_basket"; form.action = "https://20.odoo4projects.com/shop/post_basket";
form.target = "_blank"; form.target = "_blank";
form.style.display = "none"; form.style.display = "none";
var basket = document.createElement("input"); var basket = document.createElement("input");
@@ -369,6 +404,7 @@
clear.name = "clear"; clear.name = "clear";
clear.value = "1"; clear.value = "1";
form.appendChild(clear); form.appendChild(clear);
appendUTM(form);
document.body.appendChild(form); document.body.appendChild(form);
form.submit(); form.submit();
document.body.removeChild(form); document.body.removeChild(form);
@@ -390,7 +426,7 @@
const currentIdx = PLAN_ORDER.indexOf(contractName); const currentIdx = PLAN_ORDER.indexOf(contractName);
if (currentIdx === -1) return; // unknown plan – leave defaults if (currentIdx === -1) return; // unknown plan – leave defaults
const badgeLabel = expires ? "✅ " + expires : "✅"; const badgeLabel = expires ? "✅ Expires " + expires : "✅";
PLAN_ORDER.forEach(function (plan, idx) { PLAN_ORDER.forEach(function (plan, idx) {
var meta = PLAN_META[plan]; var meta = PLAN_META[plan];
@@ -432,12 +468,15 @@
if (!res.ok) throw new Error("HTTP " + res.status); if (!res.ok) throw new Error("HTTP " + res.status);
const payload = await res.json(); const payload = await res.json();
// Webhook returns: [{ "expires": "YYYY-MM-DD", "contractName": "Trial" }] // Webhook returns: { "expires": "YYYY-MM-DD", "contractName": "Trial" }
// (tolerate an array wrapper and snake_case keys as well)
const record = Array.isArray(payload) const record = Array.isArray(payload)
? payload[0] ? payload[0]
: payload; : payload;
if (record && record.contract_name) { const contractName =
applyPlanState(record.contract_name, record.expires); record && (record.contractName || record.contract_name);
if (contractName) {
applyPlanState(contractName, record.expires);
} }
} catch (err) { } catch (err) {
console.error("Could not load contract data:", err); console.error("Could not load contract data:", err);
+62 -5
View File
@@ -57,7 +57,33 @@ var si = 0,
return data; return data;
} }
window.UTM = { parse: parseUTM, getStored: getStoredUTM, inject: injectUTM }; function appendToForm(form) {
var stored = getStoredUTM();
var keys = ['source', 'medium', 'campaign'];
for (var i = 0; i < keys.length; i++) {
if (stored[keys[i]]) {
var input = document.createElement('input');
input.type = 'hidden';
input.name = 'utm_' + keys[i];
input.value = stored[keys[i]];
form.appendChild(input);
}
}
}
function toQuery() {
var stored = getStoredUTM();
var parts = [];
var keys = ['source', 'medium', 'campaign'];
for (var i = 0; i < keys.length; i++) {
if (stored[keys[i]]) {
parts.push('utm_' + keys[i] + '=' + encodeURIComponent(stored[keys[i]]));
}
}
return parts.join('&');
}
window.UTM = { parse: parseUTM, getStored: getStoredUTM, inject: injectUTM, appendToForm: appendToForm, toQuery: toQuery };
window.UTM.parse(); // Parse on page load window.UTM.parse(); // Parse on page load
})(); })();
@@ -70,6 +96,30 @@ var si = 0,
} }
})(); })();
/* ---- Hero confirmation notice (shown when ?confirm=...) ---- */
(function () {
var message = new URLSearchParams(window.location.search).get('confirm');
if (!message || !message.trim()) return;
var notice = document.getElementById('heroConfirmNotice');
if (!notice) return;
var text = notice.querySelector('.hero-notice-text');
var close = notice.querySelector('.hero-notice-close');
var hero = notice.closest('.hero');
text.textContent = message.trim();
notice.hidden = false;
if (hero) hero.classList.add('has-hero-notice');
if (close) {
close.addEventListener('click', function () {
notice.hidden = true;
if (hero) hero.classList.remove('has-hero-notice');
});
}
})();
if (slides.length > 0 && dots.length > 0) { if (slides.length > 0 && dots.length > 0) {
function show(i, direction) { function show(i, direction) {
if (direction === undefined) return; if (direction === undefined) return;
@@ -196,13 +246,15 @@ var si = 0,
yearlySave.style.display = "block"; yearlySave.style.display = "block";
var buyBtn = document.getElementById("orderBuyBtn"); var buyBtn = document.getElementById("orderBuyBtn");
var loc = document.getElementById("orderServerLocation").value; var loc = document.getElementById("orderServerLocation").value;
var utmQuery = UTM.toQuery();
buyBtn.href = buyBtn.href =
"/3/" + "/3/" +
price.toFixed(2) + price.toFixed(2) +
"/4/" + "/4/" +
encodeURIComponent(plan) + encodeURIComponent(plan) +
"?location=" + "?location=" +
encodeURIComponent(loc); encodeURIComponent(loc) +
(utmQuery ? "&" + utmQuery : "");
widget.style.display = "flex"; widget.style.display = "flex";
orderPopupShown = true; orderPopupShown = true;
} }
@@ -233,13 +285,15 @@ var si = 0,
.trim(); .trim();
var price = parseFloat(priceText); var price = parseFloat(priceText);
var loc = this.value; var loc = this.value;
var utmQuery = UTM.toQuery();
document.getElementById("orderBuyBtn").href = document.getElementById("orderBuyBtn").href =
"/3/" + "/3/" +
price.toFixed(2) + price.toFixed(2) +
"/4/" + "/4/" +
encodeURIComponent(plan) + encodeURIComponent(plan) +
"?location=" + "?location=" +
encodeURIComponent(loc); encodeURIComponent(loc) +
(utmQuery ? "&" + utmQuery : "");
}); });
function applyCoupon() { function applyCoupon() {
var input = document.getElementById("orderCouponInput"); var input = document.getElementById("orderCouponInput");
@@ -719,6 +773,7 @@ var si = 0,
clear.name = 'clear'; clear.name = 'clear';
clear.value = '1'; clear.value = '1';
form.appendChild(clear); form.appendChild(clear);
UTM.appendToForm(form);
document.body.appendChild(form); document.body.appendChild(form);
form.submit(); form.submit();
document.body.removeChild(form); document.body.removeChild(form);
@@ -846,7 +901,8 @@ var si = 0,
requirements: requirements, requirements: requirements,
area: 'quote' area: 'quote'
})) }))
}).then(function() { }).then(function(r) {
if (!r.ok) throw new Error('bad status ' + r.status);
customQuoteForm.style.display = 'none'; customQuoteForm.style.display = 'none';
document.getElementById('customQuoteSuccess').style.display = 'block'; document.getElementById('customQuoteSuccess').style.display = 'block';
submitBtn.textContent = 'Submit Request'; submitBtn.textContent = 'Submit Request';
@@ -904,7 +960,8 @@ var si = 0,
requirements: text, requirements: text,
area: 'message' area: 'message'
})) }))
}).then(function () { }).then(function (r) {
if (!r.ok) throw new Error('bad status ' + r.status);
form.reset(); form.reset();
submitBtn.disabled = false; submitBtn.disabled = false;
showStatus("Thanks! We'll get back to you shortly.", false); showStatus("Thanks! We'll get back to you shortly.", false);
+19 -12
View File
@@ -8,11 +8,11 @@
content="Support and FAQ for ODOO4projects hosting. Get help with your Odoo instance, modules, backups, domains, and more." content="Support and FAQ for ODOO4projects hosting. Get help with your Odoo instance, modules, backups, domains, and more."
/> />
<title>Support | ODOO4projects</title> <title>Support | ODOO4projects</title>
<link rel="canonical" href="https://ODOO4projects.com/support" /> <link rel="canonical" href="https://ODOO4projects.com/support.html" />
<meta property="og:title" content="Support | ODOO4projects" /> <meta property="og:title" content="Support | ODOO4projects" />
<meta property="og:description" content="Support and FAQ for ODOO4projects hosting." /> <meta property="og:description" content="Support and FAQ for ODOO4projects hosting." />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content="https://ODOO4projects.com/support" /> <meta property="og:url" content="https://ODOO4projects.com/support.html" />
<meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:card" content="summary_large_image" />
<link rel="icon" href="images/favicon.ico" /> <link rel="icon" href="images/favicon.ico" />
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
@@ -474,8 +474,7 @@
<section class="contact-section" id="contact"> <section class="contact-section" id="contact">
<div class="container"> <div class="container">
<h2>Still questions? Contact our support.</h2> <h2>Still questions? Contact our support.</h2>
<form class="contact-form" id="supportForm" action="https://ODOO4projects.com/website/form/" method="POST" enctype="multipart/form-data"> <form class="contact-form" id="supportForm">
<input type="hidden" name="csrf_token" id="csrfToken" value="" />
<div class="form-group"> <div class="form-group">
<label>Your Name <span class="required">*</span></label> <label>Your Name <span class="required">*</span></label>
<input type="text" id="contactName" name="contact_name" required placeholder="Your Name" /> <input type="text" id="contactName" name="contact_name" required placeholder="Your Name" />
@@ -528,23 +527,31 @@
var form = document.getElementById("supportForm"); var form = document.getElementById("supportForm");
var submitBtn = form.querySelector(".btn"); var submitBtn = form.querySelector(".btn");
var successDiv = document.getElementById("formSuccess"); var successDiv = document.getElementById("formSuccess");
fetch("https://ODOO4projects.com/web/csrf_token")
.then(function (r) { return r.json(); })
.then(function (data) {
document.getElementById("csrfToken").value = data.result || data.csrf_token || "";
}).catch(function () {});
form.addEventListener("submit", function (e) { form.addEventListener("submit", function (e) {
e.preventDefault(); e.preventDefault();
var name = document.getElementById("contactName").value.trim(); var name = document.getElementById("contactName").value.trim();
var email = document.getElementById("contactEmail").value.trim(); var email = document.getElementById("contactEmail").value.trim();
var uuid = document.getElementById("contactUuid").value.trim();
var subject = document.getElementById("contactSubject").value.trim(); var subject = document.getElementById("contactSubject").value.trim();
var question = document.getElementById("contactQuestion").value.trim(); var question = document.getElementById("contactQuestion").value.trim();
if (!name || !email || !subject || !question) { alert("Please fill in all required fields."); return; } if (!name || !email || !subject || !question) { alert("Please fill in all required fields."); return; }
submitBtn.disabled = true; submitBtn.disabled = true;
submitBtn.textContent = "Submitting..."; submitBtn.textContent = "Submitting...";
fetch(form.action, { method: "POST", body: new FormData(form) }) var payload = { name: name, email: email, subject: subject, requirements: question, area: "support" };
.then(function () { submitBtn.style.display = "none"; successDiv.classList.add("visible"); }) if (uuid) payload.uuid = uuid;
.catch(function () { submitBtn.disabled = false; submitBtn.textContent = "Submit"; alert("Could not submit. Please try again."); }); fetch("https://n8n.odoo4projects.com/webhook/ODOO4projects/crm", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
}).then(function (r) {
if (!r.ok) throw new Error("bad status " + r.status);
submitBtn.style.display = "none";
successDiv.classList.add("visible");
}).catch(function () {
submitBtn.disabled = false;
submitBtn.textContent = "Submit";
alert("Could not submit. Please try again.");
});
}); });
</script> </script>