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
oliver 04d39157b8 Buy Area 2026-10-08 17:28:26 -03:00
oliver 5cc0c06a11 Fix modal close + color 2026-10-08 16:29:57 -03:00
8 changed files with 290 additions and 69 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
+35 -13
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)}}
@@ -182,7 +189,7 @@
.oca-empty{text-align:center;padding:2rem;color:rgba(255,255,255,.4);font-style:italic;display:none} .oca-empty{text-align:center;padding:2rem;color:rgba(255,255,255,.4);font-style:italic;display:none}
.oca-loading{text-align:center;padding:2rem;color:rgba(255,255,255,.4);font-size:.88rem} .oca-loading{text-align:center;padding:2rem;color:rgba(255,255,255,.4);font-size:.88rem}
/* Custom Quote Modal */ /* Custom Quote Modal */
.ow-sub{font-size:.95rem;color:rgba(255,255,255,.7);margin-bottom:1.5rem} .ow-sub{font-size:.95rem;color:var(--midnight);margin-bottom:1.5rem}
.ow-panel input[type="text"],.ow-panel textarea{width:100%;padding:.8rem 1rem;border-radius:var(--radius);border:1px solid var(--line-brass);background:rgba(255,255,255,.05);color:#171c26;font-family:Inter,sans-serif;font-size:.88rem;outline:none;transition:border-color .2s,background .2s;box-sizing:border-box} .ow-panel input[type="text"],.ow-panel textarea{width:100%;padding:.8rem 1rem;border-radius:var(--radius);border:1px solid var(--line-brass);background:rgba(255,255,255,.05);color:#171c26;font-family:Inter,sans-serif;font-size:.88rem;outline:none;transition:border-color .2s,background .2s;box-sizing:border-box}
.ow-panel input[type="text"]:focus,.ow-panel textarea:focus{border-color:var(--brass);background:rgba(255,255,255,.08)} .ow-panel input[type="text"]:focus,.ow-panel textarea:focus{border-color:var(--brass);background:rgba(255,255,255,.08)}
.ow-panel textarea{min-height:100px;resize:vertical} .ow-panel textarea{min-height:100px;resize:vertical}
@@ -198,6 +205,9 @@
#customQuoteModal .biz-field input[type="email"]::placeholder{color:rgba(23,28,38,.3)} #customQuoteModal .biz-field input[type="email"]::placeholder{color:rgba(23,28,38,.3)}
#customQuoteModal .biz-field input[type="text"]{color:#171c26} #customQuoteModal .biz-field input[type="text"]{color:#171c26}
#customQuoteModal .biz-field input[type="text"]::placeholder{color:rgba(23,28,38,.3)} #customQuoteModal .biz-field input[type="text"]::placeholder{color:rgba(23,28,38,.3)}
/* Success message sits on the light modal panel, so it needs dark text (the global .biz-success rules target the dark wizard section) */
#customQuoteModal .biz-success h3{color:var(--midnight)}
#customQuoteModal .biz-success p{color:var(--midnight)}
@media(max-width:600px){.oca-table td,.oca-table th{padding:.5rem .65rem;font-size:.8rem}.ow-panel{left:5%;right:5%}.ow-close{top:.5rem;right:.5rem;font-size:1.6rem}} @media(max-width:600px){.oca-table td,.oca-table th{padding:.5rem .65rem;font-size:.8rem}.ow-panel{left:5%;right:5%}.ow-close{top:.5rem;right:.5rem;font-size:1.6rem}}
</style> </style>
<link rel="stylesheet" href="style.css" media="print" onload="this.media='all'" /> <link rel="stylesheet" href="style.css" media="print" onload="this.media='all'" />
@@ -208,14 +218,19 @@
THESIS: The homepage as a global business lounge concierge desk — midnight blue, brass, marble, city placards for the six regions. The category default (hero + feature grid + pricing grid) is reframed as hospitality: the visitor checks in, reads the rate card, and books a suite. THESIS: The homepage as a global business lounge concierge desk — midnight blue, brass, marble, city placards for the six regions. The category default (hero + feature grid + pricing grid) is reframed as hospitality: the visitor checks in, reads the rate card, and books a suite.
OWN-WORLD: Midnight blue (#0d1b2e) ground, brass (#c9a227) for every accent and CTA, cream (#f4f0e8) for light surfaces. Marcellus serif for display, Inter for body. Six city photos (Amsterdam, Boston, London, Mumbai, São Paulo, Sydney) as circular placards. Hairline brass rules. Concierge-card features. OWN-WORLD: Midnight blue (#0d1b2e) ground, brass (#c9a227) for every accent and CTA, cream (#f4f0e8) for light surfaces. Marcellus serif for display, Inter for body. Six city photos (Amsterdam, Boston, London, Mumbai, São Paulo, Sydney) as circular placards. Hairline brass rules. Concierge-card features.
STORY: The visitor understands: "I can deploy Odoo in 5 minutes, globally, without DevOps. This is enterprise-grade, but the concierge handles everything." They believe it from the city photos (real regions), the partner logos, the brass CTA, and the "No setup fee. Stripe Payment. Cancel at any time" footer. STORY: The visitor understands: "I can deploy Odoo in 5 minutes, globally, without DevOps. This is enterprise-grade, but the concierge handles everything." They believe it from the city photos (real regions), the partner logos, the brass CTA, and the "No setup fee. Stripe Payment. Cancel at any time" footer.
FIRST VIEWPORT: Midnight hero with faint Amsterdam skyline. Brass kicker "FULLY MANAGED ODOO HOSTING". Large serif h1 "Deploy Odoo in 5 Minutes — Fully Managed Hosting". Stats row with brass checks. Brass CTA button "See Plans & Pricing" + ghost "How It Works". Bottom: six city placards (photo + name + region) in a horizontal strip. FIRST VIEWPORT: Midnight hero with faint Amsterdam skyline. Brass kicker "FULLY MANAGED ODOO COMMUNITY HOSTING". Large serif h1 "Deploy Odoo in 5 Minutes — Fully Managed Hosting". Stats row with brass checks. Brass CTA button "See Plans & Pricing" + ghost "How It Works". Bottom: six city placards (photo + name + region) in a horizontal strip.
FORM: The Grand Hotel Business Lounge (model-pick, user-chosen). Seed key: 7db4dced. FORM: The Grand Hotel Business Lounge (model-pick, user-chosen). Seed key: 7db4dced.
FINISH: unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, and DESIGN.md. FINISH: unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, and DESIGN.md.
--> -->
<!-- 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 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>
<p class="hero-sub">Launch a production-ready Odoo Community instance with automatic backups, free SSL, and Git-based module management. No DevOps required.</p> <p class="hero-sub">Launch a production-ready Odoo Community instance with automatic backups, free SSL, and Git-based module management. No DevOps required.</p>
<div class="hero-stats"> <div class="hero-stats">
@@ -369,7 +384,7 @@
<label for="pricingOdooVersion">Odoo Version</label> <label for="pricingOdooVersion">Odoo Version</label>
<select id="pricingOdooVersion" class="pricing-server-select"> <select id="pricingOdooVersion" class="pricing-server-select">
<option value="19.0">19.0 — Tons of OCA supported modules</option> <option value="19.0">19.0 — Tons of OCA supported modules</option>
<option value="20.0">20.0 — Latest Greatest</option> <option value="20.0" selected>20.0 — Latest Greatest</option>
</select> </select>
</div> </div>
<div class="pricing-grid"> <div class="pricing-grid">
@@ -383,7 +398,7 @@
<div class="price-save">Save 8%</div> <div class="price-save">Save 8%</div>
</div> </div>
<p class="desc">"ODOO Standard .. that is all my business needs"</p> <p class="desc">"ODOO Standard .. that is all my business needs"</p>
<a href="javascript:void(0)" class="btn btn-brass btn-buy" data-id="54">Buy Now</a> <a href="javascript:void(0)" class="btn btn-brass btn-buy" data-id="6">Buy Now</a>
<ul> <ul>
<li><i class="fas fa-check" style="color: var(--success)"></i> Launch Odoo CE in 5 minutes</li> <li><i class="fas fa-check" style="color: var(--success)"></i> Launch Odoo CE in 5 minutes</li>
<li><i class="fas fa-check" style="color: var(--success)"></i> Automatic backups — no remembering</li> <li><i class="fas fa-check" style="color: var(--success)"></i> Automatic backups — no remembering</li>
@@ -402,7 +417,7 @@
<div class="price-save">Save 9%</div> <div class="price-save">Save 9%</div>
</div> </div>
<p class="desc">"I need some modules and professional reports"</p> <p class="desc">"I need some modules and professional reports"</p>
<a href="javascript:void(0)" class="btn btn-brass btn-buy" data-id="55">Buy Now</a> <a href="javascript:void(0)" class="btn btn-brass btn-buy" data-id="4">Buy Now</a>
<ul> <ul>
<li><i class="fas fa-check" style="color: var(--success)"></i> Launch Odoo CE in 5 minutes</li> <li><i class="fas fa-check" style="color: var(--success)"></i> Launch Odoo CE in 5 minutes</li>
<li><i class="fas fa-check" style="color: var(--success)"></i> Automatic backups — no remembering</li> <li><i class="fas fa-check" style="color: var(--success)"></i> Automatic backups — no remembering</li>
@@ -422,7 +437,7 @@
<div class="price-save">Save 10%</div> <div class="price-save">Save 10%</div>
</div> </div>
<p class="desc">"ODOO Enterprise is a must have!"</p> <p class="desc">"ODOO Enterprise is a must have!"</p>
<a href="javascript:void(0)" class="btn btn-brass btn-buy" data-id="56">Buy Now</a> <a href="javascript:void(0)" class="btn btn-brass btn-buy" data-id="5">Buy Now</a>
<ul> <ul>
<li><i class="fas fa-check" style="color: var(--success)"></i> Launch Odoo CE in 5 minutes</li> <li><i class="fas fa-check" style="color: var(--success)"></i> Launch Odoo CE in 5 minutes</li>
<li><i class="fas fa-check" style="color: var(--success)"></i> Automatic backups — no remembering</li> <li><i class="fas fa-check" style="color: var(--success)"></i> Automatic backups — no remembering</li>
@@ -486,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>
@@ -611,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>
@@ -624,9 +639,8 @@
</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>
<p><a href="mailto:support@odoo4projects.com" class="footer-email">support@odoo4projects.com</a></p>
</div> </div>
<div> <div>
<h4>Follow us on</h4> <h4>Follow us on</h4>
@@ -634,6 +648,14 @@
<a href="https://www.linkedin.com/company/odoo4projects/" target="_blank" aria-label="LinkedIn"><i class="fab fa-linkedin-in"></i></a> <a href="https://www.linkedin.com/company/odoo4projects/" target="_blank" aria-label="LinkedIn"><i class="fab fa-linkedin-in"></i></a>
<a href="https://www.youtube.com/@ODOO4projects" target="_blank" aria-label="YouTube"><i class="fab fa-youtube"></i></a> <a href="https://www.youtube.com/@ODOO4projects" target="_blank" aria-label="YouTube"><i class="fab fa-youtube"></i></a>
</div> </div>
<form class="footer-contact-form" id="footerContactForm">
<input type="email" id="footerContactEmail" placeholder="Your email address" required />
<div class="footer-textarea-wrap">
<textarea id="footerContactText" placeholder="Your message..." required></textarea>
<button type="submit" class="footer-send-btn" aria-label="Send message"><i class="fas fa-paper-plane"></i></button>
</div>
<div class="footer-form-status" id="footerFormStatus" role="status"></div>
</form>
</div> </div>
</div> </div>
<div class="fcopy">Copyright &copy; ODOO4projects LLC</div> <div class="fcopy">Copyright &copy; ODOO4projects LLC</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);
+110 -6
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");
@@ -701,7 +755,7 @@ var si = 0,
var version = verSelect ? verSelect.value : ''; var version = verSelect ? verSelect.value : '';
var form = document.createElement('form'); var form = document.createElement('form');
form.method = 'POST'; form.method = 'POST';
form.action = 'https://odoo.odoo4projects.com/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');
@@ -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);
@@ -810,6 +865,9 @@ var si = 0,
document.getElementById('customQuoteForm').reset(); document.getElementById('customQuoteForm').reset();
document.getElementById('customQuoteSuccess').style.display = 'none'; document.getElementById('customQuoteSuccess').style.display = 'none';
} }
/* Expose to global scope so the inline onclick handlers in the modal markup can reach them */
window.openCustomQuoteModal = openCustomQuoteModal;
window.closeCustomQuoteModal = closeCustomQuoteModal;
document.addEventListener('keydown', function(e) { document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') { if (e.key === 'Escape') {
var modal = document.getElementById('customQuoteModal'); var modal = document.getElementById('customQuoteModal');
@@ -840,9 +898,11 @@ var si = 0,
body: JSON.stringify(UTM.inject({ body: JSON.stringify(UTM.inject({
name: name, name: name,
email: email, email: email,
requirements: requirements requirements: requirements,
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';
@@ -867,3 +927,47 @@ var si = 0,
}); });
}); });
})(); })();
/* ---- Footer contact form ---- */
(function () {
var form = document.getElementById('footerContactForm');
if (!form) return;
var emailInput = document.getElementById('footerContactEmail');
var textInput = document.getElementById('footerContactText');
var submitBtn = form.querySelector('.footer-send-btn');
var status = document.getElementById('footerFormStatus');
function showStatus(message, isError) {
status.textContent = message;
status.classList.toggle('error', !!isError);
status.classList.add('visible');
}
form.addEventListener('submit', function (e) {
e.preventDefault();
var email = emailInput.value.trim();
var text = textInput.value.trim();
if (!email || !text) return;
submitBtn.disabled = true;
status.classList.remove('visible');
fetch('https://n8n.odoo4projects.com/webhook/ODOO4projects/crm', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(UTM.inject({
email: email,
requirements: text,
area: 'message'
}))
}).then(function (r) {
if (!r.ok) throw new Error('bad status ' + r.status);
form.reset();
submitBtn.disabled = false;
showStatus("Thanks! We'll get back to you shortly.", false);
}).catch(function () {
submitBtn.disabled = false;
showStatus('Something went wrong. Please try again.', true);
});
});
})();
+67 -14
View File
@@ -920,23 +920,76 @@ img { max-width: 100%; height: auto; vertical-align: middle; }
} }
.fcopy a { color: rgba(255,255,255,0.4); } .fcopy a { color: rgba(255,255,255,0.4); }
.fcopy a:hover { color: var(--brass); } .fcopy a:hover { color: var(--brass); }
.footer-email { .footer-contact-form {
display: inline-block; margin-top: 1.25rem;
margin-top: 0.75rem; display: flex;
padding: 0.5rem 0.8rem; flex-direction: column;
background: rgba(201,162,39,0.08); gap: 0.6rem;
border: 1px solid rgba(201,162,39,0.25); }
.footer-contact-form input[type="email"],
.footer-contact-form textarea {
width: 100%;
padding: 0.6rem 0.8rem;
border-radius: var(--radius); border-radius: var(--radius);
color: var(--brass); border: 1px solid var(--line-brass);
font-family: Inter, sans-serif; background: rgba(255,255,255,0.06);
font-size: 0.85rem;
transition: all 0.2s;
}
.footer-email:hover {
background: rgba(201,162,39,0.12);
border-color: var(--brass);
color: #fff; color: #fff;
font-family: Inter, sans-serif;
font-size: 0.82rem;
line-height: 1.6;
outline: none;
box-sizing: border-box;
transition: border-color 0.2s, background 0.2s;
} }
.footer-contact-form input[type="email"]:focus,
.footer-contact-form textarea:focus {
border-color: var(--brass);
background: rgba(255,255,255,0.1);
}
.footer-contact-form input[type="email"]::placeholder,
.footer-contact-form textarea::placeholder {
color: rgba(255,255,255,0.3);
}
.footer-textarea-wrap { position: relative; }
.footer-contact-form textarea {
min-height: 84px;
padding-right: 2.6rem;
resize: vertical;
}
.footer-send-btn {
position: absolute;
right: 0.45rem;
bottom: 0.45rem;
width: 1.9rem;
height: 1.9rem;
border: none;
border-radius: 50%;
background: var(--brass);
color: var(--midnight);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.72rem;
transition: background 0.2s, transform 0.2s;
}
.footer-send-btn:hover {
background: var(--brass-bright);
transform: translateY(-1px);
}
.footer-send-btn:disabled {
opacity: 0.6;
cursor: default;
transform: none;
}
.footer-form-status {
font-size: 0.82rem;
line-height: 1.4;
color: #4ade80;
display: none;
}
.footer-form-status.visible { display: block; }
.footer-form-status.error { color: #ef4444; }
@media (max-width: 768px) { @media (max-width: 768px) {
.fgrid { grid-template-columns: 1fr; } .fgrid { grid-template-columns: 1fr; }
.footer { padding-top: 2.5rem; padding-bottom: 5rem; } .footer { padding-top: 2.5rem; padding-bottom: 5rem; }
+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>