Public Access
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a54dc22bd1 | ||
|
|
ca89d8e7b7 | ||
|
|
29127d4025 | ||
|
|
b4e0faa62e | ||
|
|
575e3efece | ||
|
|
62f92769a1 | ||
|
|
3637094896 | ||
|
|
609f9d64bf | ||
|
|
1ab6c47df6 | ||
|
|
354799b9ca |
No files matched your search
+1
-1
@@ -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
|
||||||
|
|||||||
@@ -190,7 +190,7 @@
|
|||||||
<p>
|
<p>
|
||||||
<a href="https://odoo4projects.com/legal/privacy">Privacy</a> •
|
<a href="https://odoo4projects.com/legal/privacy">Privacy</a> •
|
||||||
<a href="https://odoo4projects.com/legal/terms">Terms</a> •
|
<a href="https://odoo4projects.com/legal/terms">Terms</a> •
|
||||||
<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
@@ -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">×</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">✓ Coupon applied</p>
|
<p class="ow-coupon-status" id="orderCouponStatus">✓ Coupon applied</p>
|
||||||
</div>
|
</div>
|
||||||
<a id="orderBuyBtn" href="/contactus" class="btn btn-brass ow-buy">Continue to Stripe →</a>
|
<a id="orderBuyBtn" href="/support.html#contact" class="btn btn-brass ow-buy">Continue to Stripe →</a>
|
||||||
<p class="ow-note">🔒 Secure Stripe checkout · Credit card required</p>
|
<p class="ow-note">🔒 Secure Stripe checkout · 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
@@ -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
@@ -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);
|
||||||
|
|||||||
@@ -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
@@ -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>
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user