Compare commits
131 Commits
ab15ba5a4f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30ed470a1a | ||
| 4320ef22b1 | |||
|
|
c06b9f27b5 | ||
|
|
88e38a7c00 | ||
|
|
a1035c87d6 | ||
|
|
ab6ed50cd9 | ||
| bf29824c0b | |||
|
|
e056e8e01f | ||
| 7ab6dde1a4 | |||
| 7cd8bc54e9 | |||
|
|
c462d75c4c | ||
|
|
88a99d4942 | ||
|
|
04555d17ff | ||
|
|
a57452e764 | ||
|
|
b33b93d3b7 | ||
|
|
12b888a678 | ||
| 8849e5035c | |||
| 7a9874b6ec | |||
|
|
a14f49fdb4 | ||
|
|
baad50071d | ||
|
|
e8fa02b6b6 | ||
|
|
f72690988e | ||
|
|
4aea655837 | ||
|
|
fa6f967778 | ||
| e81876e542 | |||
|
|
3459deb219 | ||
|
|
59501a259e | ||
|
|
3c94fb782f | ||
|
|
7f77ffb6d0 | ||
|
|
7461225230 | ||
|
|
e681478550 | ||
|
|
b3a16f81c8 | ||
|
|
f3c2acfae7 | ||
|
|
53204119a1 | ||
| 8232058ec5 | |||
|
|
d82a0dc71c | ||
|
|
e7c48b9eb3 | ||
|
|
9e263483c0 | ||
| dd5b49b46a | |||
|
|
f71c8f3da7 | ||
|
|
478e23b337 | ||
|
|
73c0be90f2 | ||
|
|
f29022d6e0 | ||
| f3b715f87c | |||
|
|
96e38f194f | ||
|
|
499e49360a | ||
| dc7218ba82 | |||
|
|
48d152e6e4 | ||
| cc0364974e | |||
| 7e3ea8a2e6 | |||
|
|
5bb66af177 | ||
|
|
95f66ce8bb | ||
|
|
a88559b4ad | ||
| ad8acab32c | |||
|
|
136c189224 | ||
| be856f3a43 | |||
| 286c7bfa10 | |||
| 098e275871 | |||
| 8e99082864 | |||
| 2e584f4a9c | |||
| a4192411a6 | |||
|
|
d99446a317 | ||
|
|
aaa94dc559 | ||
|
|
74edc1c870 | ||
|
|
859840c63e | ||
|
|
ef82235057 | ||
|
|
6adf95ea2f | ||
|
|
2d5edcbdfb | ||
|
|
ff580e0d20 | ||
|
|
b440f99449 | ||
|
|
f2bb664baa | ||
|
|
9a11d86497 | ||
|
|
15a755937c | ||
|
|
b3adf938c3 | ||
|
|
eea991a680 | ||
| 72eb69e6cc | |||
| 8c84296948 | |||
|
|
95f5b955b4 | ||
| 8107e6003b | |||
| 5abd47ab7e | |||
| 382b02c5e8 | |||
| d975586f89 | |||
| cc47d591cf | |||
| 30b24a0fe1 | |||
|
|
64c6ba4b22 | ||
|
|
d57a28d7a6 | ||
|
|
55536a20ed | ||
| cbf8ab4622 | |||
| 64ca9123b2 | |||
| 2805eb94a2 | |||
| 8b0cae4437 | |||
| 80715c0640 | |||
|
|
26440cbffb | ||
| de8d1af83d | |||
| 1745ebce21 | |||
| 1b95180ca6 | |||
| 02e2c14a5c | |||
|
|
aa1ed0129d | ||
|
|
d19aa9196a | ||
|
|
96fbab191e | ||
|
|
8eb0deda05 | ||
|
|
ae00faa031 | ||
|
|
95f1cb9a4c | ||
|
|
53acd80b21 | ||
|
|
c73d566c25 | ||
|
|
d20d5706aa | ||
|
|
d0e361b154 | ||
|
|
cd25240ad1 | ||
|
|
2e12c7e685 | ||
|
|
ed23263084 | ||
|
|
58cca9e3d2 | ||
|
|
a8a4203778 | ||
|
|
979e4f9ac0 | ||
|
|
4629df910a | ||
|
|
1798c48d3b | ||
|
|
2122dd6602 | ||
|
|
da5202b99e | ||
|
|
d07cba231f | ||
|
|
8d1576eee7 | ||
|
|
682d820f2c | ||
|
|
e0444dbd47 | ||
|
|
5f419d580f | ||
|
|
95771e4f54 | ||
|
|
6511c71a03 | ||
|
|
d8f7706c33 | ||
|
|
e927ae5de6 | ||
|
|
8d7cc60518 | ||
|
|
7695e30d59 | ||
|
|
abe9ae4712 | ||
|
|
948e09b621 | ||
|
|
16e9ad67e9 |
BIN
public/agenda/q1-2026.pdf
Normal file
BIN
public/agenda/q2-2026.pdf
Normal file
BIN
public/agenda/q3-2026.pdf
Normal file
BIN
public/agenda/q4-2026.pdf
Normal file
227
public/app.js
@@ -1,21 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* Function to handle the scroll behavior of the navigation bar
|
||||||
|
*/
|
||||||
|
|
||||||
|
let header = document.querySelector('.navbar-main');
|
||||||
|
let buttonMobile = document.getElementById('Burger-menu');
|
||||||
|
let nav = document.querySelector('nav');
|
||||||
|
let links = document.querySelectorAll('nav ul li a');
|
||||||
|
|
||||||
|
const scrollFunction = () => {
|
||||||
|
if (
|
||||||
|
document.body.scrollTop > 100 ||
|
||||||
|
document.documentElement.scrollTop > 100
|
||||||
|
) {
|
||||||
|
header.classList.add("bg");
|
||||||
|
} else {
|
||||||
|
header.classList.remove("bg");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('scroll', scrollFunction);
|
||||||
|
window.addEventListener('load', scrollFunction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to handle the accordion behavior
|
||||||
|
* for the FAQ section
|
||||||
|
*/
|
||||||
|
|
||||||
const accTitles = document.querySelectorAll('.accordion-title');
|
const accTitles = document.querySelectorAll('.accordion-title');
|
||||||
|
|
||||||
|
function closeAllAccordions(exceptThis = null) {
|
||||||
|
accTitles.forEach(title => {
|
||||||
|
if (title !== exceptThis) {
|
||||||
|
title.classList.remove('active');
|
||||||
|
const content = title.nextElementSibling;
|
||||||
|
content.style.maxHeight = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function openAccordion(title) {
|
||||||
|
const content = title.nextElementSibling;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
content.style.maxHeight = content.scrollHeight + 'px';
|
||||||
|
});
|
||||||
|
title.classList.add('active');
|
||||||
|
}
|
||||||
|
|
||||||
accTitles.forEach(title => {
|
accTitles.forEach(title => {
|
||||||
title.addEventListener('click', () => {
|
title.addEventListener('click', () => {
|
||||||
accTitles.forEach(otherTitle => {
|
|
||||||
if (otherTitle !== title) {
|
|
||||||
otherTitle.classList.remove('active');
|
|
||||||
otherTitle.nextElementSibling.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const content = title.nextElementSibling;
|
const content = title.nextElementSibling;
|
||||||
const isOpen = content.style.display === 'block';
|
const isOpen = title.classList.contains('active');
|
||||||
title.classList.toggle('active');
|
|
||||||
content.style.display = isOpen ? 'none' : 'block';
|
if (isOpen) {
|
||||||
|
// Close current
|
||||||
|
title.classList.remove('active');
|
||||||
|
content.style.maxHeight = null;
|
||||||
|
} else {
|
||||||
|
// Close others, open this
|
||||||
|
closeAllAccordions(title);
|
||||||
|
openAccordion(title);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Adjust height on resize (especially for images inside content)
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
accTitles.forEach(title => {
|
||||||
|
if (title.classList.contains('active')) {
|
||||||
|
const content = title.nextElementSibling;
|
||||||
|
content.style.maxHeight = content.scrollHeight + 'px';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to handle team section slider
|
||||||
|
*/
|
||||||
|
|
||||||
const slides = document.querySelectorAll('.slide');
|
const slides = document.querySelectorAll('.slide');
|
||||||
let currentIndex = 0;
|
let currentIndex = 0;
|
||||||
|
|
||||||
@@ -32,126 +93,40 @@ if (slides.length > 0) {
|
|||||||
setInterval(nextSlide, 10000);
|
setInterval(nextSlide, 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
(function () {
|
/**
|
||||||
const preamble = `
|
* Function to handle the blog teaser toggle
|
||||||
We use what we preach — this chatbot is powered by our own n8n automation 🤖 to help you quickly find what you need.
|
* for showing full content
|
||||||
|
*/
|
||||||
|
|
||||||
Want to talk to a real automation expert? Just buy a service pack 💼 — it includes a 1-hour get-to-know session with our team 👥.
|
function toggleContent(button) {
|
||||||
|
const teaser = button.parentElement;
|
||||||
If it’s not the right fit, no worries — we’ll refund you 💸.
|
const fullContent = teaser.querySelector('.blog-full-content');
|
||||||
`;
|
if (fullContent.style.display === 'none') {
|
||||||
|
fullContent.style.display = 'block';
|
||||||
const logo="logo.svg"
|
button.innerHTML = 'Read Less <span class="read-less-btn-icon"><i class="fa-solid fa-angle-up"></i></span>';
|
||||||
const api='https://ai.odoo4projects.com/webhook/81742473-b50b-4845-a5f9-916d9fe60876/chat'
|
button.classList.add('read-less-btn');
|
||||||
|
} else {
|
||||||
// Elements
|
fullContent.style.display = 'none';
|
||||||
const chatToggle = document.getElementById('cw-chatToggle');
|
button.innerHTML = 'Read More <span class="read-more-btn-icon"><i class="fa-solid fa-angle-right"></i></span>';
|
||||||
const chatWidget = document.getElementById('cw-chatWidget');
|
|
||||||
const chatForm = document.getElementById('cw-chatForm');
|
|
||||||
const chatInput = document.getElementById('cw-chatInput');
|
|
||||||
const chatMessages = document.getElementById('cw-chatMessages');
|
|
||||||
const sessionId = crypto.randomUUID();
|
|
||||||
|
|
||||||
let chatOpened = false;
|
|
||||||
|
|
||||||
function appendMessage(text, sender) {
|
|
||||||
const msg = document.createElement('div');
|
|
||||||
msg.classList.add('cw-message', sender === 'user' ? 'user' : 'bot');
|
|
||||||
msg.innerHTML = text;
|
|
||||||
|
|
||||||
chatMessages.appendChild(msg);
|
|
||||||
chatMessages.scrollTop = chatMessages.scrollHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chatToggle.addEventListener('click', () => {
|
|
||||||
const isVisible = chatWidget.classList.toggle('active');
|
|
||||||
if (isVisible && !chatOpened) {
|
|
||||||
appendMessage(
|
|
||||||
preamble,
|
|
||||||
'bot'
|
|
||||||
);
|
|
||||||
chatOpened = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
chatForm.addEventListener('submit', async (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
const input = chatInput.value.trim();
|
|
||||||
if (!input) return;
|
|
||||||
appendMessage(input, 'user');
|
|
||||||
chatInput.value = '';
|
|
||||||
chatInput.focus();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(api, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ action: 'sendMessage', sessionId, chatInput: input })
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
console.log("12344")
|
|
||||||
const statusDiv = document.getElementById('cw-status');
|
|
||||||
console.log("ASS")
|
|
||||||
console.log(data)
|
|
||||||
if (data.status) {
|
|
||||||
statusDiv.innerHTML = data.status;
|
|
||||||
|
|
||||||
// Wait one frame to ensure DOM is updated
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
|
|
||||||
statusDiv.style.padding = '10px';
|
|
||||||
statusDiv.style.maxHeight = statusDiv.scrollHeight + 'px';
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
statusDiv.style.maxHeight = '0';
|
|
||||||
statusDiv.style.padding = '0 10px';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to handle the mobile menu toggle
|
||||||
|
*/
|
||||||
|
|
||||||
|
const mobMenu = () => {
|
||||||
appendMessage(data.output, 'bot');
|
for (let i = 0; i < links.length; i++) {
|
||||||
} catch (error) {
|
links[i].addEventListener('click', mobMenu)
|
||||||
appendMessage('Fehler beim Verbinden mit dem Server. Bitte versuchen Sie es später erneut.', 'bot');
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function handleBuyClick(buttonId, message) {
|
|
||||||
const btn = document.getElementById(buttonId);
|
|
||||||
if (!btn) return;
|
|
||||||
|
|
||||||
btn.addEventListener('click', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (!chatWidget.classList.contains('active')) {
|
|
||||||
chatWidget.classList.add('active');
|
|
||||||
if (!chatOpened) {
|
|
||||||
appendMessage(preamble, 'bot');
|
|
||||||
chatOpened = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
appendMessage(message, 'user');
|
|
||||||
|
|
||||||
fetch(api, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ action: 'sendMessage', sessionId, chatInput: message })
|
|
||||||
})
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then((data) => {
|
|
||||||
appendMessage(data.output, 'bot');
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
appendMessage('Fehler beim Verbinden mit dem Server. Bitte versuchen Sie es später erneut.', 'bot');
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
if (nav.classList.contains('responsive')) {
|
||||||
|
nav.classList.remove('responsive');
|
||||||
|
document.body.style.overflow = '';
|
||||||
|
|
||||||
handleBuyClick('buy-3h', 'I want to buy the 3 Hours pack for $450.');
|
} else {
|
||||||
handleBuyClick('buy-5h', 'I want to buy the 5 Hours pack for $675.');
|
nav.classList.add('responsive');
|
||||||
handleBuyClick('buy-10h', 'I want to buy the 10 Hours pack for $1200.');
|
document.body.style.overflow = 'hidden';
|
||||||
handleBuyClick('buy-bundle', 'I want to buy the ODOO and N8N bundle for $395 per year.');
|
}
|
||||||
})();
|
}
|
||||||
|
|
||||||
|
buttonMobile.addEventListener('click', mobMenu);
|
||||||
21
public/brandize.html
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>OD8N - Odoo & n8n Automation Experts</title>
|
||||||
|
|
||||||
|
<script>const configUrl = `https://od8n.com/widget/custom/brandize.json`;</script>
|
||||||
|
<script src="widget/widget.js"></script>
|
||||||
|
<script type="module" src="widget/custom/brandize.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="widget/custom/brandize.css">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
public/button.png
Normal file
|
After Width: | Height: | Size: 121 KiB |
220
public/buyModal.js
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
const WEBHOOK_URL = "https://002-001-5dd6e535-4d1c-46bc-9bd9-42ad4bc5f082.odoo4projects.com/webhook/c76e6b4e-af2f-4bc3-9875-6460d0ffc8e3";
|
||||||
|
|
||||||
|
function createModal() {
|
||||||
|
const modal = document.createElement("div");
|
||||||
|
modal.id = "buyNowModal";
|
||||||
|
modal.style.position = "fixed";
|
||||||
|
modal.style.top = "0";
|
||||||
|
modal.style.left = "0";
|
||||||
|
modal.style.width = "100%";
|
||||||
|
modal.style.height = "100%";
|
||||||
|
modal.style.backgroundColor = "rgba(0,0,0,0.6)";
|
||||||
|
modal.style.display = "none";
|
||||||
|
modal.style.justifyContent = "center";
|
||||||
|
modal.style.alignItems = "center";
|
||||||
|
modal.style.zIndex = "1000";
|
||||||
|
|
||||||
|
modal.innerHTML = `
|
||||||
|
<div style="
|
||||||
|
background: #ffffff;
|
||||||
|
padding: 40px 30px;
|
||||||
|
border-radius: 16px;
|
||||||
|
max-width: 500px;
|
||||||
|
width: 90%;
|
||||||
|
position: relative;
|
||||||
|
font-family: 'Arial', sans-serif;
|
||||||
|
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
|
||||||
|
">
|
||||||
|
<span id="closeModal" style="
|
||||||
|
position: absolute;
|
||||||
|
top: 15px;
|
||||||
|
right: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #555;
|
||||||
|
">×</span>
|
||||||
|
|
||||||
|
<h2 style="margin-bottom: 15px; font-size: 24px; color: #333;">Order Details</h2>
|
||||||
|
<p id="productText" style="margin-bottom: 25px; font-weight: 500; color: #555;"></p>
|
||||||
|
|
||||||
|
<form id="buyForm" style="display: flex; flex-direction: column; gap: 15px;">
|
||||||
|
|
||||||
|
<!-- Hidden select, shown only if product starts with "_" -->
|
||||||
|
<select name="location" id="locationSelect" required style="
|
||||||
|
display: none;
|
||||||
|
padding: 12px 15px;
|
||||||
|
font-size: 16px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 8px;
|
||||||
|
outline: none;
|
||||||
|
">
|
||||||
|
<option value="">Select Location</option>
|
||||||
|
<option value="Boston">US, Boston</option>
|
||||||
|
<option value="Manchester">UK, Manchester</option>
|
||||||
|
<option value="Mumbai">IN, Mumbai</option>
|
||||||
|
<option value="Saopaulo">BR, Sao Paulo</option>
|
||||||
|
<option value="meppel">NL, Meppel</option>
|
||||||
|
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<input type="text" name="name" placeholder="Name" required style="padding: 12px 15px; font-size: 16px; border: 1px solid #ccc; border-radius: 8px; outline: none;">
|
||||||
|
<input type="text" name="company" placeholder="Company" required style="padding: 12px 15px; font-size: 16px; border: 1px solid #ccc; border-radius: 8px; outline: none;">
|
||||||
|
<input type="text" name="country" placeholder="Country" required style="padding: 12px 15px; font-size: 16px; border: 1px solid #ccc; border-radius: 8px; outline: none;">
|
||||||
|
<input type="text" name="street" placeholder="Street" required style="padding: 12px 15px; font-size: 16px; border: 1px solid #ccc; border-radius: 8px; outline: none;">
|
||||||
|
<div style="display: flex; gap: 10px;">
|
||||||
|
<input type="text" name="zip" placeholder="ZIP" required style="max-width: 100px; flex: 1 1 0; padding: 12px 10px; font-size: 16px; border: 1px solid #ccc; border-radius: 8px;">
|
||||||
|
<input type="text" name="town" placeholder="Town" required style="flex: 2 1 0; padding: 12px 10px; font-size: 16px; border: 1px solid #ccc; border-radius: 8px;">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="email" name="email" placeholder="Email" required style="padding: 12px 15px; font-size: 16px; border: 1px solid #ccc; border-radius: 8px; outline: none;">
|
||||||
|
|
||||||
|
<input type="hidden" name="product">
|
||||||
|
<input type="hidden" name="price">
|
||||||
|
|
||||||
|
<button id="submitBuy" type="submit" style="
|
||||||
|
padding: 14px;
|
||||||
|
background: #007BFF;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
transition: background 0.3s;
|
||||||
|
">Send Order</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="confirmation" style="
|
||||||
|
display: none;
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #e6ffed;
|
||||||
|
color: #056608;
|
||||||
|
border-radius: 12px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 500;
|
||||||
|
">
|
||||||
|
<p>Thank you for your purchase! 🎉</p>
|
||||||
|
<button id="closeConfirmation" style="
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background: #007BFF;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
transition: background 0.3s;
|
||||||
|
">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.appendChild(modal);
|
||||||
|
|
||||||
|
// Close modal
|
||||||
|
document.getElementById("closeModal").onclick = () => { document.getElementById("buyNowModal").style.display = "none"; };
|
||||||
|
document.getElementById("closeConfirmation").onclick = () => {
|
||||||
|
document.getElementById("confirmation").style.display = "none";
|
||||||
|
document.getElementById("buyNowModal").style.display = "none";
|
||||||
|
};
|
||||||
|
modal.onclick = (e) => { if (e.target === modal) modal.style.display = "none"; };
|
||||||
|
|
||||||
|
return modal;
|
||||||
|
}
|
||||||
|
|
||||||
|
function openModal(productHref) {
|
||||||
|
const modal = document.getElementById("buyNowModal");
|
||||||
|
modal.style.display = "flex";
|
||||||
|
|
||||||
|
// Reset form display for repeated orders
|
||||||
|
const form = modal.querySelector("#buyForm");
|
||||||
|
const confirmation = modal.querySelector("#confirmation");
|
||||||
|
form.style.display = "flex"; // show form
|
||||||
|
confirmation.style.display = "none"; // hide confirmation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let product = productHref;
|
||||||
|
let price = "";
|
||||||
|
if (productHref.includes("/")) {
|
||||||
|
const parts = productHref.split("/").filter(Boolean);
|
||||||
|
product = parts[parts.length - 2] || "Product";
|
||||||
|
price = parts[parts.length - 1] || "0";
|
||||||
|
}
|
||||||
|
// Show/hide location select
|
||||||
|
const locationSelect = document.getElementById("locationSelect");
|
||||||
|
if (product.startsWith("_")) {
|
||||||
|
locationSelect.style.display = "block";
|
||||||
|
locationSelect.setAttribute("required", "true");
|
||||||
|
} else {
|
||||||
|
locationSelect.style.display = "none";
|
||||||
|
locationSelect.removeAttribute("required");
|
||||||
|
locationSelect.value = ""; // reset
|
||||||
|
}
|
||||||
|
product = product.replace(/_/g, ""); // This needs to be after the locationSelect show ;)
|
||||||
|
|
||||||
|
modal.querySelector('input[name="product"]').value = product;
|
||||||
|
modal.querySelector('input[name="price"]').value = price;
|
||||||
|
modal.querySelector("#productText").textContent = `You will buy ${product} for $${price}.`;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function handleFormSubmit() {
|
||||||
|
const form = document.getElementById("buyForm");
|
||||||
|
const confirmation = document.getElementById("confirmation");
|
||||||
|
|
||||||
|
if (!form) {
|
||||||
|
console.error("Form not found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.addEventListener("submit", async (e) => {
|
||||||
|
console.log("handler");
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const data = {};
|
||||||
|
new FormData(form).forEach((value, key) => (data[key] = value));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(WEBHOOK_URL, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
form.style.display = "none";
|
||||||
|
confirmation.style.display = "block";
|
||||||
|
form.reset();
|
||||||
|
} else {
|
||||||
|
alert("Failed to submit form.");
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
alert("Error submitting form.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function attachButtons() {
|
||||||
|
const buttons = Array.from(document.querySelectorAll("button, a"));
|
||||||
|
buttons.forEach(btn => {
|
||||||
|
const text = btn.textContent.trim();
|
||||||
|
if (text === "Buy Now" || text === "Book Now") {
|
||||||
|
btn.addEventListener("click", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const href = btn.getAttribute("href") || btn.dataset.product || "Unknown/0";
|
||||||
|
openModal(href);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
createModal();
|
||||||
|
handleFormSubmit();
|
||||||
|
attachButtons();
|
||||||
|
});
|
||||||
|
|
||||||
6
public/icons/logo-white.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<svg width="150" height="49" viewBox="0 0 150 49" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M16.4955 15.3691C7.40148 15.3691 0 22.6877 0 31.6972C0 40.7066 7.40148 48.0252 16.4955 48.0252C25.5894 48.0252 32.9909 40.7066 32.9909 31.6972C32.9909 22.6877 25.5894 15.3691 16.4955 15.3691ZM16.4955 42.7508C10.3318 42.7508 5.30482 37.7792 5.30482 31.6719C5.30482 25.5647 10.3318 20.5931 16.4955 20.5931C22.6591 20.5931 27.6861 25.5647 27.6861 31.6719C27.6861 37.7792 22.6591 42.7508 16.4955 42.7508Z" fill="white"/>
|
||||||
|
<path d="M66.487 0C64.8703 0 63.582 1.28707 63.582 2.90221V20.2397C60.8538 17.817 57.3425 15.8486 53.5281 15.8486C49.158 15.8486 45.192 17.6404 42.3375 20.5678C39.4577 23.47 37.6895 27.5079 37.6895 31.9243C37.6895 36.3659 39.4577 40.3786 42.3375 43.2808C45.2172 46.183 49.158 48 53.5281 48C57.8983 48 61.8643 46.2082 64.7188 43.2808C67.4975 40.4543 69.2405 36.6183 69.3415 32.3533C69.3668 32.2271 69.3668 32.1009 69.3668 31.9748V2.90221C69.3921 1.28707 68.0785 0 66.487 0ZM53.5281 42.5237C47.5918 42.5237 42.9943 38.0568 42.9943 31.9243C42.9943 25.7918 47.5918 21.3249 53.5281 21.3249C59.4645 21.3249 63.8094 25.7918 63.8094 31.9243C63.8094 38.0568 59.4645 42.5237 53.5281 42.5237Z" fill="white"/>
|
||||||
|
<path d="M135.323 15.571C127.088 15.571 120.647 22.6877 120.647 31.7729V44.6183C120.647 46.2334 121.682 47.5205 123.299 47.5205C124.916 47.5205 126.204 46.2334 126.204 44.6183V31.7729C126.204 25.9432 130.347 21.3754 135.323 21.3754C140.249 21.3754 144.367 25.8675 144.443 31.6215L144.417 44.6183C144.417 46.2334 145.706 47.5205 147.322 47.5205C148.939 47.5205 149.975 46.2334 149.975 44.6183V32.2019L150 31.9495V31.7981C150 22.6877 143.533 15.571 135.323 15.571Z" fill="white"/>
|
||||||
|
<path d="M102.055 19.2555C103.596 17.5899 104.53 15.3691 104.53 12.9464C104.53 7.7981 100.337 3.60883 95.1836 3.60883C90.0303 3.60883 85.837 7.7981 85.837 12.9464C85.837 15.3691 86.7717 17.5899 88.3126 19.2555C81.9721 21.5268 77.5261 26.8517 77.5261 33.0347C77.5261 41.2871 85.4581 48 95.2088 48C104.96 48 112.892 41.2871 112.892 33.0347C112.841 26.8517 108.395 21.5268 102.055 19.2555ZM95.1583 8.65614C97.5329 8.65614 99.4527 10.5741 99.4527 12.9464C99.4527 15.3186 97.5329 17.2366 95.1583 17.2366C92.7838 17.2366 90.864 15.3186 90.864 12.9464C90.864 10.5741 92.7838 8.65614 95.1583 8.65614ZM95.1583 41.9937C88.742 41.9937 83.5383 37.9811 83.5383 33.0347C83.5383 28.0883 88.742 23.3186 95.1583 23.3186C101.575 23.3186 106.778 28.0883 106.778 33.0347C106.778 37.9811 101.575 41.9937 95.1583 41.9937Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
BIN
public/images/bitcoin-2894068_1280.jpg
Normal file
|
After Width: | Height: | Size: 250 KiB |
BIN
public/images/chat_widget.png
Normal file
|
After Width: | Height: | Size: 248 KiB |
BIN
public/images/coach.jpg
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
public/images/hostinger.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/images/humanintheloop.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
public/images/mockup-5222446_1280.jpg
Normal file
|
After Width: | Height: | Size: 147 KiB |
BIN
public/images/money-3219298_1280.jpg
Normal file
|
After Width: | Height: | Size: 211 KiB |
BIN
public/images/money-3545832_1280.jpg
Normal file
|
After Width: | Height: | Size: 309 KiB |
BIN
public/images/odoo_integration.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
public/images/odoo_node.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
public/images/online_shop.jpg
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
public/images/open.jpg
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/images/server.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
public/images/server.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
public/images/settings.png
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
public/images/share.jpg
Normal file
|
After Width: | Height: | Size: 244 KiB |
BIN
public/images/simple_vector_store.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
public/images/startup-3267505_1280.jpg
Normal file
|
After Width: | Height: | Size: 268 KiB |
BIN
public/images/startup_learning.jpg
Normal file
|
After Width: | Height: | Size: 229 KiB |
BIN
public/images/startup_office.jpg
Normal file
|
After Width: | Height: | Size: 216 KiB |
BIN
public/images/transaction.jpg
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
public/images/youtube.jpg
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
public/images/youtube_display.jpg
Normal file
|
After Width: | Height: | Size: 135 KiB |
701
public/index.html.design
Normal file
@@ -0,0 +1,701 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<script defer data-domain="od8n.com" src="https://plausible.odoo4projects.com/js/script.tagged-events.js"></script>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="Unlock your business potential with OD8N, your expert partners in Odoo and n8n automation. Get a free 1-hour consultation with our automation engineers. Risk-free guarantee!">
|
||||||
|
<meta name="keywords" content="OD8N, Odoo, n8n, automation, business automation, consulting, integration, service packs, Odoo development, n8n workflows">
|
||||||
|
<meta name="author" content="OD8N">
|
||||||
|
<title>OD8N - Odoo & n8n Automation Experts</title>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
|
||||||
|
<script>const configUrl = `https://od8n.com/widget/custom/od8n.json`;</script>
|
||||||
|
<script src="widget/widget.js"></script>
|
||||||
|
<link rel="stylesheet" href="widget/custom/od8n.css">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N",
|
||||||
|
"url": "https://www.od8n.com/",
|
||||||
|
"logo": "https://www.od8n.com/logo.svg",
|
||||||
|
"description": "OD8N are experts in Odoo and n8n automation, offering flexible man-hour service packs with a free 1-hour consultation.",
|
||||||
|
"contactPoint": {
|
||||||
|
"@type": "ContactPoint",
|
||||||
|
"telephone": "",
|
||||||
|
"contactType": "customer service"
|
||||||
|
},
|
||||||
|
"sameAs": []
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Service",
|
||||||
|
"serviceType": "Odoo & n8n Automation Consulting",
|
||||||
|
"provider": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N"
|
||||||
|
},
|
||||||
|
"name": "3 Hours Service Pack",
|
||||||
|
"description": "Quick fixes and small automation improvements.",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "450",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Service",
|
||||||
|
"serviceType": "Odoo & n8n Automation Consulting",
|
||||||
|
"provider": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N"
|
||||||
|
},
|
||||||
|
"name": "5 Hours Service Pack",
|
||||||
|
"description": "Ideal for mid-level integrations and custom workflows.",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "675",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Service",
|
||||||
|
"serviceType": "Odoo & n8n Automation Consulting",
|
||||||
|
"provider": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N"
|
||||||
|
},
|
||||||
|
"name": "10 Hours Service Pack",
|
||||||
|
"description": "Perfect for large projects and advanced automation.",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "1200",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Service",
|
||||||
|
"serviceType": "Odoo & n8n Automation Consulting",
|
||||||
|
"provider": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N"
|
||||||
|
},
|
||||||
|
"name": "ODOO & N8N Bundle",
|
||||||
|
"description": "Perfect for taking conrtol over your company automation installation.",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "395",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Person",
|
||||||
|
"name": "Oliver Arnold",
|
||||||
|
"jobTitle": "Expert in Odoo & System Design",
|
||||||
|
"worksFor": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Person",
|
||||||
|
"name": "Mark Gutmann",
|
||||||
|
"jobTitle": "Expert in AI and Process Consulting",
|
||||||
|
"worksFor": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- Header Section -->
|
||||||
|
<header class="hero" id="home">
|
||||||
|
<div class="navbar-main">
|
||||||
|
<div class="logo">
|
||||||
|
<a href="/" class="logo-link" aria-label="Go to homepage">
|
||||||
|
<img src="./icons/logo-white.svg" alt="OD8N Logo" class="logo-icon">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<nav>
|
||||||
|
<button id="Burger-menu">
|
||||||
|
<i class="fa-solid fa-bars"></i>
|
||||||
|
</button>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#home">Home</a></li>
|
||||||
|
<li><a href="#packages">packages</a></li>
|
||||||
|
<li><a href="#team">Team</a></li>
|
||||||
|
<li><a href="#blog">Blog</a></li>
|
||||||
|
<li><a href="#story">Story</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<section class="hero-content">
|
||||||
|
<h1>Odoo & n8n Automation Experts</h1>
|
||||||
|
<p>We charge upfront — this lets us skip the sales talk and give serious clients immediate access to our best engineers.</p>
|
||||||
|
<ul class="hero-list">
|
||||||
|
<li><span class="icon"><i class="fa-solid fa-circle-check"></i></span><span>One-hour get-to-know session included — not satisfied? Full refund, no questions asked</span></li>
|
||||||
|
<li><span class="icon"><i class="fa-solid fa-circle-check"></i></span><span>Experts in Odoo and n8n — no outsourcing, no fluff</span></li>
|
||||||
|
<li><span class="icon"><i class="fa-solid fa-circle-check"></i></span><span>Hosting solutions for Odoo & n8n available</span></li>
|
||||||
|
<li><span class="icon"><i class="fa-solid fa-circle-check"></i></span><span>Custom development tailored to your workflows</span></li>
|
||||||
|
</ul>
|
||||||
|
<button class="hero-button-cta plausible-event-name=ExplorePackages" onclick="location.href='#packages'">Explore packages</button>
|
||||||
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Product Packages -->
|
||||||
|
<section id="packages" class="packages">
|
||||||
|
<h2 class="section-header">Service Packs</h2>
|
||||||
|
<div class="package-list container">
|
||||||
|
<div class="package">
|
||||||
|
<h3>3 Hours<span class="asteric-icon">*</span></h3>
|
||||||
|
<p>Quick fixes and small automation improvements.</p>
|
||||||
|
<span class="price">$450</span>
|
||||||
|
<button class="btn-secondary plausible-event-name=ChoosePlan" onclick="sendMessageToBot('I want to buy 3 Hours of service for $450')">
|
||||||
|
Choose Plan
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="package featured">
|
||||||
|
<div class="badge">Most popular</div>
|
||||||
|
<h3>5 Hours<span class="asteric-icon">*</span></h3>
|
||||||
|
<p>Ideal for mid-level integrations and custom workflows.</p>
|
||||||
|
<span class="price">$675</span>
|
||||||
|
|
||||||
|
<button class="btn-secondary btn-featured" onclick="sendMessageToBot('I want to buy 5 hours of service for $675')">
|
||||||
|
Choose Plan
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="package">
|
||||||
|
<h3>10 Hours<span class="asteric-icon">*</span></h3>
|
||||||
|
<p>Perfect for large projects and advanced automation.</p>
|
||||||
|
<span class="price">$1.200</span>
|
||||||
|
<button class="btn-secondary plausible-event-name=ChoosePlan" onclick="sendMessageToBot('I want to buy 10 hours of service for $1.200')">
|
||||||
|
Choose Plan
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="package">
|
||||||
|
<h3>N8N Installation and Maintainance<span class="asteric-icon">*</span></h3>
|
||||||
|
<p>We install N8N on your Container and maintain it for one year.</p>
|
||||||
|
<span class="price">$75/Year</span>
|
||||||
|
<button class="btn-secondary plausible-event-name=ChoosePlan" onclick="sendMessageToBot('I want you to install N8N on my container and maintain it.')">
|
||||||
|
Subscribe
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="free-offer"><span class="asteric-icon">*</span> All hour packs include <strong>1 Free Consulting Hour for first clients</strong> — with a 100% refund if you’re not satisfied!</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Image Slider -->
|
||||||
|
<section id="team" class="slider-section">
|
||||||
|
<h2 class="section-header">Meet Our Team</h2>
|
||||||
|
|
||||||
|
<div class="slide container">
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="slide-image">
|
||||||
|
<img src="oliver.webp" alt="Oliver Arnold, Odoo & System Design Expert at OD8N">
|
||||||
|
</div>
|
||||||
|
<div class="slide-text">
|
||||||
|
<h2>Oliver Arnold</h2>
|
||||||
|
<h4>Expert in Odoo & System Design</h4>
|
||||||
|
<p>I am an expert in Odoo and system design with years of experience in consulting.</p>
|
||||||
|
<ul>
|
||||||
|
<li>Odoo functional consulting & development</li>
|
||||||
|
<li>N8N workflow design & custom nodes</li>
|
||||||
|
<li>System integration & architecture design</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="slide container">
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="slide-image">
|
||||||
|
<img src="mark.webp" alt="Mark Gutmann, AI and Process Consulting Expert at OD8N">
|
||||||
|
</div>
|
||||||
|
<div class="slide-text">
|
||||||
|
<h2>Mark Gutmann</h2>
|
||||||
|
<h4>Expert in AI and Process Consulting</h4>
|
||||||
|
<p>I am an expert in Odoo and system design with years of experience in consulting.</p>
|
||||||
|
<ul>
|
||||||
|
<li>Odoo functional consulting & development</li>
|
||||||
|
<li>N8N workflow design & custom nodes</li>
|
||||||
|
<li>System integration & architecture design</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="blog" class="accordion-section blog-section">
|
||||||
|
<h2 class="section-header">Latest Blog Posts</h2>
|
||||||
|
<div class="blog-list container">
|
||||||
|
|
||||||
|
<!-- 1. Example HTML to use badge in blog post -->
|
||||||
|
|
||||||
|
<!-- <div class="blog-teaser blog-badge-green">
|
||||||
|
<div class="blog-badge-green-tag">Company</div>
|
||||||
|
<h3 class="blog-title tutorial"> From Chat to Checkout: Building a Dynamic Chat Widget with PayPal and n8n</h3>
|
||||||
|
<small class="blog-date">30.07.2025</small>
|
||||||
|
<div class="blog-snippet">
|
||||||
|
So you've wired up a chat with your AI agent and it responds nicely — but what if your chat could guide users through an entire procurement flow and end with a PayPal payment button, ready to go?
|
||||||
|
</div>
|
||||||
|
<div class="blog-full-content" style="display:none;">
|
||||||
|
<p>
|
||||||
|
So you've wired up a chat with your AI agent and it responds nicely — but what if your chat could <strong>guide users through an entire procurement flow</strong> and end with a PayPal payment button, ready to go?
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button class="read-more-btn plausible-event-name=ReadPost" onclick="toggleContent(this)">Read More <span class="read-more-btn-icon"><i class="fa-solid fa-angle-right"></i></span></button>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 2. Example HTML to skip badge in blog post -->
|
||||||
|
|
||||||
|
<!-- <div class="blog-teaser">
|
||||||
|
<h3 class="blog-title tutorial"> From Chat to Checkout: Building a Dynamic Chat Widget with PayPal and n8n</h3>
|
||||||
|
<small class="blog-date">30.07.2025</small>
|
||||||
|
<div class="blog-snippet">
|
||||||
|
So you've wired up a chat with your AI agent and it responds nicely — but what if your chat could guide users through an entire procurement flow and end with a PayPal payment button, ready to go?
|
||||||
|
</div>
|
||||||
|
<div class="blog-full-content" style="display:none;">
|
||||||
|
<p>
|
||||||
|
So you've wired up a chat with your AI agent and it responds nicely — but what if your chat could <strong>guide users through an entire procurement flow</strong> and end with a PayPal payment button, ready to go?
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button class="read-more-btn plausible-event-name=ReadPost" onclick="toggleContent(this)">Read More <span class="read-more-btn-icon"><i class="fa-solid fa-angle-right"></i></span></button>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<!-- 3. Uncomment this to get one blog post ready with blue badge -->
|
||||||
|
|
||||||
|
<!-- <div class="blog-teaser blog-badge-blue">
|
||||||
|
<div class="blog-badge-blue-tag">Most popular</div>
|
||||||
|
<h3 class="blog-title tutorial"> From Chat to Checkout: Building a Dynamic Chat Widget with PayPal and n8n</h3>
|
||||||
|
<small class="blog-date">30.07.2025</small>
|
||||||
|
<div class="blog-snippet">
|
||||||
|
So you've wired up a chat with your AI agent and it responds nicely — but what if your chat could guide users through an entire procurement flow and end with a PayPal payment button, ready to go?
|
||||||
|
</div>
|
||||||
|
<div class="blog-full-content" style="display:none;">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
So you've wired up a chat with your AI agent and it responds nicely — but what if your chat could <strong>guide users through an entire procurement flow</strong> and end with a PayPal payment button, ready to go?
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In this tutorial, we’ll walk through the key steps we used to build a <strong>dynamic chat widget</strong> using <code>n8n</code>, an AI agent, and a smart process flow that finishes in PayPal. We won’t cover the basics of implementing an AI chat agent — we’ll assume you’ve got that part covered.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">💡 The Real Magic: State-Aware Chat Responses</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The key innovation here lies in how we return the agent’s response to the frontend. Instead of sending back a simple string, we return a rich object that contains not just the output text, but also a dynamic <strong>state object</strong> that tracks context and next steps.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Here’s what our return looks like from the backend:</p>
|
||||||
|
|
||||||
|
<pre><code>return {
|
||||||
|
json: {
|
||||||
|
output: output_,
|
||||||
|
state: state_
|
||||||
|
}
|
||||||
|
};</code></pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This small design decision opens up a world of flexibility. The frontend can now dynamically react to the current state of the conversation — whether it’s collecting user details, offering product options, or finalizing a purchase.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">🛒 Embedding the Product ID in State</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Once the conversation has gathered enough information from the user (product type, quantity, shipping address, etc.), we instruct the AI agent to <strong>embed the product ID directly into the state object</strong>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This ID is then parsed by the frontend to dynamically display the appropriate <strong>PayPal payment button</strong>, configured for the selected product and amount.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
It’s a smooth handoff: the chat does the heavy lifting, and the UI reacts based on structured, predictable metadata.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">🔧 Under the Hood: What We Used</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><strong>n8n</strong> for workflow logic and webhook handling</li>
|
||||||
|
<li><strong>Custom HTML + JS widget</strong> to handle frontend interaction</li>
|
||||||
|
<li><strong>OpenAI Agent</strong> with system prompts to guide the process</li>
|
||||||
|
<li><strong>PayPal API</strong> for seamless payment integration</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">✨ Bonus: A Process Wizard</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
We also built a simple process wizard UI that activates when certain states are reached. This provides users with an optional visual flow, letting them see how far along they are in the checkout process — especially useful when the chat is collecting structured information.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">📚 Want to Try This Yourself?</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Head over to our <a href="/">homepage</a> to read more blog posts like this and explore our implementation in detail.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Or, if you'd like to help us out with a little SEO love, just Google <strong>"N8N ODOO API"</strong> and click on our homepage: <strong>OD8N</strong>. As a reward, we’ve got an in-depth breakdown of the full implementation waiting for you!
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Here’s a full video walkthrough of the dynamic chat widget in action:</p>
|
||||||
|
<span class="blog-video-description">
|
||||||
|
In this tutorial, we’ll walk through the key steps we used to build a dynamic chat widget using n8n, an AI agent, and a smart process flow that finishes in PayPal. We won’t cover the basics of implementing an AI chat agent — we’ll assume you’ve got that part covered.
|
||||||
|
|
||||||
|
💡 The Real Magic: State-Aware Chat Responses
|
||||||
|
The key innovation here lies in how we return the agent’s response to the frontend. Instead of sending back a simple string, we return a rich object that contains not just the output text, but also a dynamic state object that tracks context and next steps.
|
||||||
|
|
||||||
|
Here’s what our return looks like from the backend:
|
||||||
|
|
||||||
|
return {
|
||||||
|
json: {
|
||||||
|
output: output_,
|
||||||
|
state: state_
|
||||||
|
}
|
||||||
|
};
|
||||||
|
This small design decision opens up a world of flexibility. The frontend can now dynamically react to the current state of the conversation — whether it’s collecting user details, offering product options, or finalizing a purchase.
|
||||||
|
|
||||||
|
🛒 Embedding the Product ID in State
|
||||||
|
Once the conversation has gathered enough information from the user (product type, quantity, shipping address, etc.), we instruct the AI agent to embed the product ID directly into the state object.
|
||||||
|
|
||||||
|
This ID is then parsed by the frontend to dynamically display the appropriate PayPal payment button, configured for the selected product and amount.
|
||||||
|
|
||||||
|
It’s a smooth handoff: the chat does the heavy lifting, and the UI reacts based on structured, predictable metadata.
|
||||||
|
|
||||||
|
🔧 Under the Hood: What We Used
|
||||||
|
n8n for workflow logic and webhook handling
|
||||||
|
Custom HTML + JS widget to handle frontend interaction
|
||||||
|
OpenAI Agent with system prompts to guide the process
|
||||||
|
PayPal API for seamless payment integration
|
||||||
|
✨ Bonus: A Process Wizard
|
||||||
|
We also built a simple process wizard UI that activates when certain states are reached. This provides users with an optional visual flow, letting them see how far along they are in the checkout process — especially useful when the chat is collecting structured information.
|
||||||
|
|
||||||
|
📚 Want to Try This Yourself?
|
||||||
|
Head over to our homepage to read more blog posts like this and explore our implementation in detail.
|
||||||
|
|
||||||
|
Or, if you'd like to help us out with a little SEO love, just Google "N8N ODOO API" and click on our homepage: OD8N. As a reward, we’ve got an in-depth breakdown of the full implementation waiting for you!
|
||||||
|
|
||||||
|
Here’s a full video walkthrough of the dynamic chat widget in action:
|
||||||
|
</span>
|
||||||
|
<iframe width="560" height="315" class="ytvideo" src="https://youtu.be/4BPLTfeQfHE" title="Video" frameborder="0"
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||||
|
allowfullscreen>
|
||||||
|
</iframe>
|
||||||
|
</div>
|
||||||
|
<button class="read-more-btn plausible-event-name=ReadPost" onclick="toggleContent(this)">Read More <span class="read-more-btn-icon"><i class="fa-solid fa-angle-right"></i></span></button>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<div class="blog-teaser">
|
||||||
|
<h3 class="blog-title tutorial"> From Chat to Checkout: Building a Dynamic Chat Widget with PayPal and n8n</h3>
|
||||||
|
<small class="blog-date">30.07.2025</small>
|
||||||
|
<div class="blog-snippet">
|
||||||
|
So you've wired up a chat with your AI agent and it responds nicely — but what if your chat could guide users through an entire procurement flow and end with a PayPal payment button, ready to go?
|
||||||
|
</div>
|
||||||
|
<div class="blog-full-content" style="display:none;">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
So you've wired up a chat with your AI agent and it responds nicely — but what if your chat could <strong>guide users through an entire procurement flow</strong> and end with a PayPal payment button, ready to go?
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In this tutorial, we’ll walk through the key steps we used to build a <strong>dynamic chat widget</strong> using <code>n8n</code>, an AI agent, and a smart process flow that finishes in PayPal. We won’t cover the basics of implementing an AI chat agent — we’ll assume you’ve got that part covered.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">💡 The Real Magic: State-Aware Chat Responses</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The key innovation here lies in how we return the agent’s response to the frontend. Instead of sending back a simple string, we return a rich object that contains not just the output text, but also a dynamic <strong>state object</strong> that tracks context and next steps.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Here’s what our return looks like from the backend:</p>
|
||||||
|
|
||||||
|
<pre><code>return {
|
||||||
|
json: {
|
||||||
|
output: output_,
|
||||||
|
state: state_
|
||||||
|
}
|
||||||
|
};</code></pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This small design decision opens up a world of flexibility. The frontend can now dynamically react to the current state of the conversation — whether it’s collecting user details, offering product options, or finalizing a purchase.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">🛒 Embedding the Product ID in State</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Once the conversation has gathered enough information from the user (product type, quantity, shipping address, etc.), we instruct the AI agent to <strong>embed the product ID directly into the state object</strong>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This ID is then parsed by the frontend to dynamically display the appropriate <strong>PayPal payment button</strong>, configured for the selected product and amount.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
It’s a smooth handoff: the chat does the heavy lifting, and the UI reacts based on structured, predictable metadata.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">🔧 Under the Hood: What We Used</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><strong>n8n</strong> for workflow logic and webhook handling</li>
|
||||||
|
<li><strong>Custom HTML + JS widget</strong> to handle frontend interaction</li>
|
||||||
|
<li><strong>OpenAI Agent</strong> with system prompts to guide the process</li>
|
||||||
|
<li><strong>PayPal API</strong> for seamless payment integration</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">✨ Bonus: A Process Wizard</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
We also built a simple process wizard UI that activates when certain states are reached. This provides users with an optional visual flow, letting them see how far along they are in the checkout process — especially useful when the chat is collecting structured information.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">📚 Want to Try This Yourself?</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Head over to our <a href="/">homepage</a> to read more blog posts like this and explore our implementation in detail.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Or, if you'd like to help us out with a little SEO love, just Google <strong>"N8N ODOO API"</strong> and click on our homepage: <strong>OD8N</strong>. As a reward, we’ve got an in-depth breakdown of the full implementation waiting for you!
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Here’s a full video walkthrough of the dynamic chat widget in action:</p>
|
||||||
|
<span class="blog-video-description">
|
||||||
|
In this tutorial, we’ll walk through the key steps we used to build a dynamic chat widget using n8n, an AI agent, and a smart process flow that finishes in PayPal. We won’t cover the basics of implementing an AI chat agent — we’ll assume you’ve got that part covered.
|
||||||
|
|
||||||
|
💡 The Real Magic: State-Aware Chat Responses
|
||||||
|
The key innovation here lies in how we return the agent’s response to the frontend. Instead of sending back a simple string, we return a rich object that contains not just the output text, but also a dynamic state object that tracks context and next steps.
|
||||||
|
|
||||||
|
Here’s what our return looks like from the backend:
|
||||||
|
|
||||||
|
return {
|
||||||
|
json: {
|
||||||
|
output: output_,
|
||||||
|
state: state_
|
||||||
|
}
|
||||||
|
};
|
||||||
|
This small design decision opens up a world of flexibility. The frontend can now dynamically react to the current state of the conversation — whether it’s collecting user details, offering product options, or finalizing a purchase.
|
||||||
|
|
||||||
|
🛒 Embedding the Product ID in State
|
||||||
|
Once the conversation has gathered enough information from the user (product type, quantity, shipping address, etc.), we instruct the AI agent to embed the product ID directly into the state object.
|
||||||
|
|
||||||
|
This ID is then parsed by the frontend to dynamically display the appropriate PayPal payment button, configured for the selected product and amount.
|
||||||
|
|
||||||
|
It’s a smooth handoff: the chat does the heavy lifting, and the UI reacts based on structured, predictable metadata.
|
||||||
|
|
||||||
|
🔧 Under the Hood: What We Used
|
||||||
|
n8n for workflow logic and webhook handling
|
||||||
|
Custom HTML + JS widget to handle frontend interaction
|
||||||
|
OpenAI Agent with system prompts to guide the process
|
||||||
|
PayPal API for seamless payment integration
|
||||||
|
✨ Bonus: A Process Wizard
|
||||||
|
We also built a simple process wizard UI that activates when certain states are reached. This provides users with an optional visual flow, letting them see how far along they are in the checkout process — especially useful when the chat is collecting structured information.
|
||||||
|
|
||||||
|
📚 Want to Try This Yourself?
|
||||||
|
Head over to our homepage to read more blog posts like this and explore our implementation in detail.
|
||||||
|
|
||||||
|
Or, if you'd like to help us out with a little SEO love, just Google "N8N ODOO API" and click on our homepage: OD8N. As a reward, we’ve got an in-depth breakdown of the full implementation waiting for you!
|
||||||
|
|
||||||
|
Here’s a full video walkthrough of the dynamic chat widget in action:
|
||||||
|
</span>
|
||||||
|
<iframe width="560" height="315" class="ytvideo" src="https://youtu.be/4BPLTfeQfHE" title="Video" frameborder="0"
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||||
|
allowfullscreen>
|
||||||
|
</iframe>
|
||||||
|
</div>
|
||||||
|
<button class="read-more-btn plausible-event-name=ReadPost" onclick="toggleContent(this)">Read More <span class="read-more-btn-icon"><i class="fa-solid fa-angle-right"></i></span></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="blog-teaser">
|
||||||
|
<h3 class="blog-title company"> ODOO & N8N: Our Strategy</h3>
|
||||||
|
<small class="blog-date">31.07.2025</small>
|
||||||
|
<div class="blog-snippet">
|
||||||
|
<p>At the heart of every modern enterprise lies the need to balance two forces: stability and agility. Our approach harnesses the best of both worlds—leveraging the proven foundation of <strong>ODOO</strong> while embracing the innovation engine of <strong>N8N</strong>.</p>
|
||||||
|
</div>
|
||||||
|
<div class="blog-full-content" style="display:none;">
|
||||||
|
<p>At the heart of every modern enterprise lies the need to balance two forces: stability and agility. Our approach harnesses the best of both worlds—leveraging the proven foundation of <strong>ODOO</strong> while embracing the innovation engine of <strong>N8N</strong>.</p>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">ODOO: The Rock-Solid ERP Foundation</h2>
|
||||||
|
|
||||||
|
<p>We’ve seen countless ERP systems come and go. But <strong>ODOO</strong> stands tall—a battle-hardened suite refined over years of real-world application. From <strong>Accounting</strong> to <strong>CRM</strong>, <strong>Invoicing</strong>, <strong>Production</strong>, and <strong>Logistics</strong>, ODOO delivers reliable, scalable modules that form the digital spine of any serious company.</p>
|
||||||
|
|
||||||
|
<div class="highlight">
|
||||||
|
Still awesome after all these years: ODOO continues to evolve while staying true to its mission—powering real businesses with real needs.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">N8N: The Agile Integrator for the AI Era</h2>
|
||||||
|
|
||||||
|
<p>But the world is changing. Fast. AI tools are evolving weekly. APIs are everywhere. Customers demand speed and personalization like never before.</p>
|
||||||
|
|
||||||
|
<p>Enter <strong>N8N</strong>—our weapon of choice for agile automation, AI integration, and rapid deployment. Whether it's triggering actions from an AI model, syncing tools across platforms, or automating multi-step workflows, N8N gives us the power to move as fast as your market does.</p>
|
||||||
|
|
||||||
|
<p>While ODOO keeps your core business running like a well-oiled machine, N8N lets us bolt on new AI-driven capabilities almost instantly—without waiting for the next ERP update cycle.</p>
|
||||||
|
|
||||||
|
<h2 class="blog-content-section-title">Together: The Future of Digital Operations</h2>
|
||||||
|
|
||||||
|
<p>By combining ODOO and N8N, we create a powerful synergy. One gives you reliable structure. The other, unmatched flexibility. This strategy enables us to build systems that are not only stable—but also smart, adaptive, and future-ready.</p>
|
||||||
|
|
||||||
|
<div class="highlight">
|
||||||
|
💡 <strong class="blog-content-section-highlight">Smart Strategy = ODOO as the backbone + N8N as the nervous system.</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cta">
|
||||||
|
Ready to take your business operations to the next level?<br>
|
||||||
|
Let’s talk ODOO. Let’s talk N8N. Let’s build your future—today.
|
||||||
|
</div>
|
||||||
|
<img src="https://OD8N.com/images/server.webp" class="image" width="560">
|
||||||
|
</div>
|
||||||
|
<button class="read-more-btn plausible-event-name=ReadPost" onclick="toggleContent(this)">Read More <span class="read-more-btn-icon"><i class="fa-solid fa-angle-right"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Success Stories Accordion -->
|
||||||
|
<section id="story" class="accordion-section success-stories">
|
||||||
|
<h2 class="section-header">Success Stories in Automation</h2>
|
||||||
|
<div class="accordion container">
|
||||||
|
<div class="accordion-item">
|
||||||
|
<button class="accordion-title">From Manual Tracking to Automated Precision: A Retailer's Story <span class="panel-bar-title"><i class="fa-solid fa-chevron-down"></i></span></button>
|
||||||
|
<div class="accordion-content">
|
||||||
|
<section class="panel-bar-content">
|
||||||
|
<h2 class="panel-bar-content-title">The Challenge: No API, No Problem.</h2>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
A growing retail client was struggling with a major operational bottleneck: their shipping provider offered no API for tracking. This meant hours of manual data entry, a high risk of errors, and no real-time visibility into their 800+ daily shipments.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
We engineered a robust solution using n8n and Puppeteer to create a custom web scraper. This automated system intelligently mimics human interaction to extract shipment statuses twice daily, ensuring near real-time accuracy.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
<strong>The Result:</strong> Complete automation, zero manual entry, and a system that provides flawless, up-to-the-minute tracking data. All running seamlessly on our n8n community instance.
|
||||||
|
</p>
|
||||||
|
<div style="margin-top: 2em;">
|
||||||
|
<a href="#packages" class="btn-text">Automate Your Repetitive Tasks <span class="btn-text-icon"><i class="fa-solid fa-angle-right"></i></span></a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="accordion-item">
|
||||||
|
<button class="accordion-title">Scaling on Demand: Automated Odoo Instance Management <span class="panel-bar-title"><i class="fa-solid fa-chevron-down"></i></span></button>
|
||||||
|
<div class="accordion-content">
|
||||||
|
<section class="panel-bar-content">
|
||||||
|
<h2 class="panel-bar-content-title">The Challenge: Global Scale, Local Management</h2>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
ODOO4projects needed to instantly deploy new Odoo instances for clients worldwide, a process that was manual, time-consuming, and prone to configuration errors. They required a system that could scale globally and provide centralized oversight.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
We built a smart agent powered by an n8n workflow that completely automates the provisioning of Odoo instances. The system also generates a weekly server status report, providing a clear, consolidated view of their entire infrastructure.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
<strong>The Result:</strong> A fully automated, scalable, and reliable system for Odoo instance management, all running on our cost-effective n8n community instance.
|
||||||
|
</p>
|
||||||
|
<div style="margin-top: 2em;">
|
||||||
|
<a href="#packages" class="btn-text">Scale Your Operations with Automation <span class="btn-text-icon"><i class="fa-solid fa-angle-right"></i></span></a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="accordion-item">
|
||||||
|
<button class="accordion-title">From Simple Chatbot to Intelligent Odoo-Powered Agent <span class="panel-bar-title"><i class="fa-solid fa-chevron-down"></i></span></button>
|
||||||
|
<div class="accordion-content">
|
||||||
|
<section class="panel-bar-content">
|
||||||
|
<h2 class="panel-bar-content-title">The Challenge: Unlocking the Power of Conversational AI</h2>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
A client wanted to move beyond a basic FAQ chatbot. They needed an intelligent agent that could handle complex internal tasks, provide instant knowledge base access, and integrate seamlessly with their Odoo chatter.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
Leveraging powerful OCA modules and an n8n-powered backend, we built a sophisticated AI agent. This solution connects to LLMs, agents, and RAG pipelines, transforming their Odoo chatter into a powerful, intelligent hub for communication and task management.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
<strong>The Result:</strong> A truly intelligent conversational AI that streamlines employee onboarding, provides instant knowledge access, and can be embedded on any website.
|
||||||
|
</p>
|
||||||
|
<div style="margin-top: 2em;">
|
||||||
|
<a href="#packages" class="btn-text">Integrate AI into Your Workflows <span class="btn-text-icon"><i class="fa-solid fa-angle-right"></i></span></a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="accordion-item">
|
||||||
|
<button class="accordion-title">The Future of Sales: A Checkout Process Inside a Chatbox <span class="panel-bar-title"><i class="fa-solid fa-chevron-down"></i></span></button>
|
||||||
|
<div class="accordion-content">
|
||||||
|
<section class="panel-bar-content">
|
||||||
|
<h2 class="panel-bar-content-title">The Challenge: Reinventing the Sales Funnel</h2>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
We asked ourselves: could we transform a simple conversation into a complete sales transaction? The goal was to create a frictionless procurement workflow that eliminates the need for emails, forms, and spreadsheets.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
Using only n8n and PayPal, we built a revolutionary checkout process that lives entirely within a chatbox. This allows for a seamless, conversational sales experience, from initial inquiry to final purchase.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
<strong>The Result:</strong> A groundbreaking, conversational commerce solution that redefines the client interaction and digital selling. Ready to see it in action?
|
||||||
|
</p>
|
||||||
|
<div style="margin-top: 2em;">
|
||||||
|
<a href="#packages" class="btn-text">Experience the Future of Sales <span class="btn-text-icon"><i class="fa-solid fa-angle-right"></i></span></a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>For ODOO and N8N tips and tricks and news follow us on
|
||||||
|
<a href="https://www.linkedin.com/company/od8n" target="_blank" aria-label="LinkedIn"><i class="fab fa-linkedin"></i></a>
|
||||||
|
</p>
|
||||||
|
<p>© 2025 OD8N. All Rights Reserved. Service provided by ASC Consultatores Paraguay</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script defer src="./app.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
491
public/index.html.template
Normal file
@@ -0,0 +1,491 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<script defer data-domain="od8n.com" src="https://plausible.odoo4projects.com/js/script.tagged-events.js"></script>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="Unlock your business potential with OD8N, your expert partners in Odoo and n8n automation. Get a free 1-hour consultation with our automation engineers. Risk-free guarantee!">
|
||||||
|
<meta name="keywords" content="OD8N, Odoo, n8n, automation, business automation, consulting, integration, service packs, Odoo development, n8n workflows">
|
||||||
|
<meta name="author" content="OD8N">
|
||||||
|
<title>OD8N - Odoo & n8n Automation Experts</title>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
|
||||||
|
<script>const configUrl = `https://od8n.com/widget/custom/od8n.json`;</script>
|
||||||
|
<script src="widget/widget.js"></script>
|
||||||
|
<script src="buyModal.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="widget/custom/od8n.css">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N",
|
||||||
|
"url": "https://www.od8n.com/",
|
||||||
|
"logo": "https://www.od8n.com/logo.svg",
|
||||||
|
"description": "OD8N are experts in Odoo and n8n automation, offering flexible man-hour service packs with a free 1-hour consultation.",
|
||||||
|
"contactPoint": {
|
||||||
|
"@type": "ContactPoint",
|
||||||
|
"telephone": "",
|
||||||
|
"contactType": "customer service"
|
||||||
|
},
|
||||||
|
"sameAs": []
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Service",
|
||||||
|
"serviceType": "Odoo & n8n Automation Consulting",
|
||||||
|
"provider": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N"
|
||||||
|
},
|
||||||
|
"name": "3 Hours Service Pack",
|
||||||
|
"description": "Quick fixes and small automation improvements.",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "450",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Service",
|
||||||
|
"serviceType": "Odoo & n8n Automation Consulting",
|
||||||
|
"provider": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N"
|
||||||
|
},
|
||||||
|
"name": "5 Hours Service Pack",
|
||||||
|
"description": "Ideal for mid-level integrations and custom workflows.",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "675",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Service",
|
||||||
|
"serviceType": "Odoo & n8n Automation Consulting",
|
||||||
|
"provider": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N"
|
||||||
|
},
|
||||||
|
"name": "10 Hours Service Pack",
|
||||||
|
"description": "Perfect for large projects and advanced automation.",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "1200",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Service",
|
||||||
|
"serviceType": "Odoo & n8n Automation Consulting",
|
||||||
|
"provider": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N"
|
||||||
|
},
|
||||||
|
"name": "ODOO & N8N Bundle",
|
||||||
|
"description": "Perfect for taking conrtol over your company automation installation.",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "395",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Person",
|
||||||
|
"name": "Oliver Arnold",
|
||||||
|
"jobTitle": "Expert in Odoo & System Design",
|
||||||
|
"worksFor": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Person",
|
||||||
|
"name": "Mark Gutmann",
|
||||||
|
"jobTitle": "Expert in AI and Process Consulting",
|
||||||
|
"worksFor": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "OD8N"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- Header Section -->
|
||||||
|
<header class="hero" id="home">
|
||||||
|
<div class="navbar-main">
|
||||||
|
<div class="logo">
|
||||||
|
<a href="/" class="logo-link" aria-label="Go to homepage">
|
||||||
|
<img src="./icons/logo-white.svg" alt="OD8N Logo" class="logo-icon">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<nav>
|
||||||
|
<button id="Burger-menu">
|
||||||
|
<i class="fa-solid fa-bars"></i>
|
||||||
|
</button>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#home">Home</a></li>
|
||||||
|
<li><a href="#packages">Packages</a></li>
|
||||||
|
<li><a href="#team">Team</a></li>
|
||||||
|
<li><a href="#blog">Blog</a></li>
|
||||||
|
<li><a href="#story">Story</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<section class="hero-content">
|
||||||
|
<div class="hero-left">
|
||||||
|
<h1>Odoo & n8n Automation Experts</h1>
|
||||||
|
<p>We charge upfront — you will get immediate access to our best engineers.</p>
|
||||||
|
<ul class="hero-list">
|
||||||
|
<li><span class="icon"><i class="fa-solid fa-circle-check"></i></span><span>One-hour get-to-know session included — not satisfied? Full refund, no questions asked</span></li>
|
||||||
|
<li><span class="icon"><i class="fa-solid fa-circle-check"></i></span><span>Experts in Odoo and n8n — no outsourcing, no fluff</span></li>
|
||||||
|
<li><span class="icon"><i class="fa-solid fa-circle-check"></i></span><span>Hosting solutions for Odoo & n8n available</span></li>
|
||||||
|
<li><span class="icon"><i class="fa-solid fa-circle-check"></i></span><span>Custom development tailored to your workflows</span></li>
|
||||||
|
</ul>
|
||||||
|
<button class="hero-button-cta plausible-event-name=ExplorePackages" onclick="location.href='#packages'">
|
||||||
|
Explore packages
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hero-right">
|
||||||
|
<div id="my-signup-widget"></div>
|
||||||
|
<script src="https://od8n.com/widget-signup/widget.js"
|
||||||
|
data-affiliate="od8n"></script>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</header>
|
||||||
|
|
||||||
|
|
||||||
|
<section id="workshops" class="workshops">
|
||||||
|
<h2 class="section-header">Startup Workshops</h2>
|
||||||
|
<p class="section-subtitle">
|
||||||
|
We bring your business from zero to ERP and AI in just three months:
|
||||||
|
</p>
|
||||||
|
<ul class="workshop-highlights">
|
||||||
|
<li><strong>6 interactive 2-hour sessions</strong> with our expert instructors</li>
|
||||||
|
<li><strong>Hands-on topics:</strong> "First Configuration ODOO", "Sales Module", "Build your Website with ODOO", "CRM", "Automations with AI and N8N"</li>
|
||||||
|
<li><strong>Practical system setup:</strong> Work directly on your ERP so you see real results immediately</li>
|
||||||
|
<li><strong>Free tools included:</strong> ODOO and N8N for one year</li>
|
||||||
|
<li><strong>Exclusive alumni chat group:</strong> Stay connected, share tips, and get support</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="workshop-list container">
|
||||||
|
|
||||||
|
<div class="workshop">
|
||||||
|
<div class="badge next">Next</div>
|
||||||
|
<h3>Class Q1/2026</h3>
|
||||||
|
<p><strong>Language:</strong> German</p>
|
||||||
|
<p><strong>Places available:</strong> 4</p>
|
||||||
|
<a href="/agenda/q1-2026.pdf" class="agenda-link">Download Agenda</a>
|
||||||
|
<div class="workshop-action">
|
||||||
|
<span class="price">$790.00 <br> per Person</span>
|
||||||
|
<a href="https://Q1-2026/790.00"
|
||||||
|
target="_blank"
|
||||||
|
class="btn-secondary">
|
||||||
|
Book Now
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="workshop">
|
||||||
|
<h3>Class Q2/2026</h3>
|
||||||
|
<p><strong>Language:</strong> English</p>
|
||||||
|
<p><strong>Places available:</strong> 5</p>
|
||||||
|
<a href="/agenda/q2-2026.pdf" class="agenda-link">Download Agenda</a>
|
||||||
|
<div class="workshop-action">
|
||||||
|
<span class="price">$790.00 <br> per Person</span>
|
||||||
|
<a href="https://Q2-2026/790.00"
|
||||||
|
target="_blank"
|
||||||
|
class="btn-secondary">
|
||||||
|
Book Now
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="workshop">
|
||||||
|
<h3>Class Q3/2026</h3>
|
||||||
|
<p><strong>Language:</strong> German</p>
|
||||||
|
<p><strong>Places available:</strong> 6</p>
|
||||||
|
<a href="/agenda/q3-2026.pdf" class="agenda-link">Download Agenda</a>
|
||||||
|
<div class="workshop-action">
|
||||||
|
<span class="price">$790.00 <br> per Person</span>
|
||||||
|
<a href="https://Q3-2026/790.00"
|
||||||
|
target="_blank"
|
||||||
|
class="btn-secondary">
|
||||||
|
Book Now
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="workshop">
|
||||||
|
<h3>Class Q4/2026</h3>
|
||||||
|
<p><strong>Language:</strong> English</p>
|
||||||
|
<p><strong>Places available:</strong> 6</p>
|
||||||
|
<a href="/agenda/q4-2026.pdf" class="agenda-link">Download Agenda</a>
|
||||||
|
<div class="workshop-action">
|
||||||
|
<span class="price">$790.00 <br> per Person</span>
|
||||||
|
<a href="https://Q4-2026/790.00"
|
||||||
|
target="_blank"
|
||||||
|
class="btn-secondary">
|
||||||
|
Book Now
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Product Packages -->
|
||||||
|
<section id="packages" class="packages">
|
||||||
|
<h2 class="section-header">Service Packs</h2>
|
||||||
|
<div class="package-list container">
|
||||||
|
<div class="package">
|
||||||
|
<h3>3 Hours<span class="asteric-icon">*</span></h3>
|
||||||
|
<p>Quick fixes and small automation improvements.</p>
|
||||||
|
<span class="price">$450</span>
|
||||||
|
<button class="btn-secondary plausible-event-name=ChoosePlan" onclick="sendMessageToBot('I want to buy 3 Hours of service for $450')">
|
||||||
|
Choose Plan
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="package featured">
|
||||||
|
<div class="badge">Most popular</div>
|
||||||
|
<h3>5 Hours<span class="asteric-icon">*</span></h3>
|
||||||
|
<p>Ideal for mid-level integrations and custom workflows.</p>
|
||||||
|
<span class="price">$675</span>
|
||||||
|
|
||||||
|
<button class="btn-secondary btn-featured" onclick="sendMessageToBot('I want to buy 5 hours of service for $675')">
|
||||||
|
Choose Plan
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="package">
|
||||||
|
<h3>10 Hours<span class="asteric-icon">*</span></h3>
|
||||||
|
<p>Perfect for large projects and advanced automation.</p>
|
||||||
|
<span class="price">$1.200</span>
|
||||||
|
<button class="btn-secondary plausible-event-name=ChoosePlan" onclick="sendMessageToBot('I want to buy 10 hours of service for $1.200')">
|
||||||
|
Choose Plan
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="package">
|
||||||
|
<h3>N8N Installation and Maintainance<span class="asteric-icon">*</span></h3>
|
||||||
|
<p>We install N8N on your Container and maintain it for one year.</p>
|
||||||
|
<span class="price">$75/Year</span>
|
||||||
|
<button class="btn-secondary plausible-event-name=ChoosePlan" onclick="sendMessageToBot('I want you to install N8N on my container and maintain it.')">
|
||||||
|
Subscribe
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="free-offer"><span class="asteric-icon">*</span> All hour packs include <strong>1 Free Consulting Hour for first clients</strong> — with a 100% refund if you’re not satisfied!</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Image Slider -->
|
||||||
|
<section id="team" class="slider-section">
|
||||||
|
<h2 class="section-header">Meet Our Team</h2>
|
||||||
|
|
||||||
|
<div class="slide container">
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="slide-image">
|
||||||
|
<img src="oliver.webp" alt="Oliver Arnold, Odoo & System Design Expert at OD8N">
|
||||||
|
</div>
|
||||||
|
<div class="slide-text">
|
||||||
|
<h2>Oliver Arnold</h2>
|
||||||
|
<h4>Expert in Odoo & System Design</h4>
|
||||||
|
<p>I am an expert in Odoo and system design with years of experience in consulting.</p>
|
||||||
|
<ul>
|
||||||
|
<li>Odoo functional consulting & development</li>
|
||||||
|
<li>N8N workflow design & custom nodes</li>
|
||||||
|
<li>System integration & architecture design</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="slide container">
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="slide-image">
|
||||||
|
<img src="mark.webp" alt="Mark Gutmann, AI and Process Consulting Expert at OD8N">
|
||||||
|
</div>
|
||||||
|
<div class="slide-text">
|
||||||
|
<h2>Mark Gutmann</h2>
|
||||||
|
<h4>Expert in AI and Process Consulting</h4>
|
||||||
|
<p>I am an expert in Odoo and system design with years of experience in consulting.</p>
|
||||||
|
<ul>
|
||||||
|
<li>Odoo functional consulting & development</li>
|
||||||
|
<li>N8N workflow design & custom nodes</li>
|
||||||
|
<li>System integration & architecture design</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="accordion-section">
|
||||||
|
<h2 class="section-header">Latest Blog Posts</h2>
|
||||||
|
<div class="blog-list container">
|
||||||
|
<BLOG>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Success Stories Accordion -->
|
||||||
|
<section id="story" class="accordion-section success-stories">
|
||||||
|
<h2 class="section-header">Success Stories in Automation</h2>
|
||||||
|
<div class="accordion container">
|
||||||
|
<div class="accordion-item">
|
||||||
|
<button class="accordion-title">From Manual Tracking to Automated Precision: A Retailer's Story <span class="panel-bar-title"><i class="fa-solid fa-chevron-down"></i></span></button>
|
||||||
|
<div class="accordion-content">
|
||||||
|
<section class="panel-bar-content">
|
||||||
|
<h2 class="panel-bar-content-title">The Challenge: No API, No Problem.</h2>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
A growing retail client was struggling with a major operational bottleneck: their shipping provider offered no API for tracking. This meant hours of manual data entry, a high risk of errors, and no real-time visibility into their 800+ daily shipments.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
We engineered a robust solution using n8n and Puppeteer to create a custom web scraper. This automated system intelligently mimics human interaction to extract shipment statuses twice daily, ensuring near real-time accuracy.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
<strong>The Result:</strong> Complete automation, zero manual entry, and a system that provides flawless, up-to-the-minute tracking data. All running seamlessly on our n8n community instance.
|
||||||
|
</p>
|
||||||
|
<div style="margin-top: 2em;">
|
||||||
|
<a href="#packages" class="btn-text">Automate Your Repetitive Tasks <span class="btn-text-icon"><i class="fa-solid fa-angle-right"></i></span></a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="accordion-item">
|
||||||
|
<button class="accordion-title">Scaling on Demand: Automated Odoo Instance Management <span class="panel-bar-title"><i class="fa-solid fa-chevron-down"></i></span></button>
|
||||||
|
<div class="accordion-content">
|
||||||
|
<section class="panel-bar-content">
|
||||||
|
<h2 class="panel-bar-content-title">The Challenge: Global Scale, Local Management</h2>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
ODOO4projects needed to instantly deploy new Odoo instances for clients worldwide, a process that was manual, time-consuming, and prone to configuration errors. They required a system that could scale globally and provide centralized oversight.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
We built a smart agent powered by an n8n workflow that completely automates the provisioning of Odoo instances. The system also generates a weekly server status report, providing a clear, consolidated view of their entire infrastructure.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
<strong>The Result:</strong> A fully automated, scalable, and reliable system for Odoo instance management, all running on our cost-effective n8n community instance.
|
||||||
|
</p>
|
||||||
|
<div style="margin-top: 2em;">
|
||||||
|
<a href="#packages" class="btn-text">Scale Your Operations with Automation <span class="btn-text-icon"><i class="fa-solid fa-angle-right"></i></span></a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="accordion-item">
|
||||||
|
<button class="accordion-title">From Simple Chatbot to Intelligent Odoo-Powered Agent <span class="panel-bar-title"><i class="fa-solid fa-chevron-down"></i></span></button>
|
||||||
|
<div class="accordion-content">
|
||||||
|
<section class="panel-bar-content">
|
||||||
|
<h2 class="panel-bar-content-title">The Challenge: Unlocking the Power of Conversational AI</h2>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
A client wanted to move beyond a basic FAQ chatbot. They needed an intelligent agent that could handle complex internal tasks, provide instant knowledge base access, and integrate seamlessly with their Odoo chatter.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
Leveraging powerful OCA modules and an n8n-powered backend, we built a sophisticated AI agent. This solution connects to LLMs, agents, and RAG pipelines, transforming their Odoo chatter into a powerful, intelligent hub for communication and task management.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
<strong>The Result:</strong> A truly intelligent conversational AI that streamlines employee onboarding, provides instant knowledge access, and can be embedded on any website.
|
||||||
|
</p>
|
||||||
|
<div style="margin-top: 2em;">
|
||||||
|
<a href="#packages" class="btn-text">Integrate AI into Your Workflows <span class="btn-text-icon"><i class="fa-solid fa-angle-right"></i></span></a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="accordion-item">
|
||||||
|
<button class="accordion-title">The Future of Sales: A Checkout Process Inside a Chatbox <span class="panel-bar-title"><i class="fa-solid fa-chevron-down"></i></span></button>
|
||||||
|
<div class="accordion-content">
|
||||||
|
<section class="panel-bar-content">
|
||||||
|
<h2 class="panel-bar-content-title">The Challenge: Reinventing the Sales Funnel</h2>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
We asked ourselves: could we transform a simple conversation into a complete sales transaction? The goal was to create a frictionless procurement workflow that eliminates the need for emails, forms, and spreadsheets.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
Using only n8n and PayPal, we built a revolutionary checkout process that lives entirely within a chatbox. This allows for a seamless, conversational sales experience, from initial inquiry to final purchase.
|
||||||
|
</p>
|
||||||
|
<p class="panel-bar-content-text">
|
||||||
|
<strong>The Result:</strong> A groundbreaking, conversational commerce solution that redefines the client interaction and digital selling. Ready to see it in action?
|
||||||
|
</p>
|
||||||
|
<div style="margin-top: 2em;">
|
||||||
|
<a href="#packages" class="btn-text">Experience the Future of Sales <span class="btn-text-icon"><i class="fa-solid fa-angle-right"></i></span></a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>For ODOO and N8N tips and tricks and news follow us on
|
||||||
|
<a href="https://www.linkedin.com/company/od8n" target="_blank" aria-label="LinkedIn"><i class="fab fa-linkedin"></i></a>
|
||||||
|
</p>
|
||||||
|
<p>© 2025 OD8N. All Rights Reserved. Service provided by ASC Consultatores Paraguay</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script defer src="./app.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1261
public/style.css
167
public/tryNow.js
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
const TRYNOW_WEBHOOK_URL = "https://002-001-5dd6e535-4d1c-46bc-9bd9-42ad4bc5f082.odoo4projects.com/webhook/c25169c6-4234-4b47-8e74-612b9539da0a";
|
||||||
|
|
||||||
|
function tryNow_createModal() {
|
||||||
|
const modal = document.createElement("div");
|
||||||
|
modal.id = "trynowModal";
|
||||||
|
modal.style.position = "fixed";
|
||||||
|
modal.style.top = "0";
|
||||||
|
modal.style.left = "0";
|
||||||
|
modal.style.width = "100%";
|
||||||
|
modal.style.height = "100%";
|
||||||
|
modal.style.backgroundColor = "rgba(0,0,0,0.6)";
|
||||||
|
modal.style.display = "none";
|
||||||
|
modal.style.justifyContent = "center";
|
||||||
|
modal.style.alignItems = "center";
|
||||||
|
modal.style.zIndex = "1000";
|
||||||
|
|
||||||
|
modal.innerHTML = `
|
||||||
|
<div style="
|
||||||
|
background: #ffffff;
|
||||||
|
padding: 40px 30px;
|
||||||
|
border-radius: 16px;
|
||||||
|
max-width: 400px;
|
||||||
|
width: 90%;
|
||||||
|
position: relative;
|
||||||
|
font-family: 'Arial', sans-serif;
|
||||||
|
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
|
||||||
|
">
|
||||||
|
<span id="trynowCloseModal" style="
|
||||||
|
position: absolute;
|
||||||
|
top: 15px;
|
||||||
|
right: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #555;
|
||||||
|
">×</span>
|
||||||
|
|
||||||
|
<h2 style="margin-bottom: 20px; font-size: 24px; color: #333;">Order Details</h2>
|
||||||
|
|
||||||
|
<form id="trynowForm" style="display: flex; flex-direction: column; gap: 15px;">
|
||||||
|
<input type="email" name="email" placeholder="Email" required style="padding: 12px 15px; font-size: 16px; border: 1px solid #ccc; border-radius: 8px; outline: none;">
|
||||||
|
|
||||||
|
<select name="location" id="trynowLocationSelect" required style="padding: 12px 15px; font-size: 16px; border: 1px solid #ccc; border-radius: 8px; outline: none;">
|
||||||
|
<option value="">Select Location</option>
|
||||||
|
<option value="Boston">Boston</option>
|
||||||
|
<option value="Manchester">Manchester</option>
|
||||||
|
<option value="Mumbai">Mumbai</option>
|
||||||
|
<option value="Saopaulo">Sao Paulo</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select name="product" required style="padding: 12px 15px; font-size: 16px; border: 1px solid #ccc; border-radius: 8px; outline: none;">
|
||||||
|
<option value="odoo_19" selected>ODOO</option>
|
||||||
|
<option value="N8N">n8n</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<button type="submit" style="
|
||||||
|
padding: 14px;
|
||||||
|
background: #007BFF;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
transition: background 0.3s;
|
||||||
|
">Start free Trial</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="trynowConfirmation" style="
|
||||||
|
display: none;
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #e6ffed;
|
||||||
|
color: #056608;
|
||||||
|
border-radius: 12px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 500;
|
||||||
|
">
|
||||||
|
<p>Thank you for your submission! 🎉</p>
|
||||||
|
<button id="trynowCloseConfirmation" style="
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background: #007BFF;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
transition: background 0.3s;
|
||||||
|
">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.appendChild(modal);
|
||||||
|
|
||||||
|
// Close modal handlers
|
||||||
|
document.getElementById("trynowCloseModal").onclick = () => { modal.style.display = "none"; };
|
||||||
|
document.getElementById("trynowCloseConfirmation").onclick = () => {
|
||||||
|
document.getElementById("trynowConfirmation").style.display = "none";
|
||||||
|
modal.style.display = "none";
|
||||||
|
};
|
||||||
|
modal.onclick = (e) => { if (e.target === modal) modal.style.display = "none"; };
|
||||||
|
|
||||||
|
return modal;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryNow_handleFormSubmit() {
|
||||||
|
const form = document.getElementById("trynowForm");
|
||||||
|
const confirmation = document.getElementById("trynowConfirmation");
|
||||||
|
|
||||||
|
form.addEventListener("submit", async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const data = {};
|
||||||
|
new FormData(form).forEach((value, key) => (data[key] = value));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(TRYNOW_WEBHOOK_URL, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
form.style.display = "none";
|
||||||
|
confirmation.style.display = "block";
|
||||||
|
form.reset();
|
||||||
|
} else {
|
||||||
|
alert("Failed to submit form.");
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
alert("Error submitting form.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryNow_attachButtons() {
|
||||||
|
const buttons = Array.from(document.querySelectorAll("a, button"));
|
||||||
|
buttons.forEach(btn => {
|
||||||
|
if (btn.textContent && btn.textContent.trim() === "Try Now") {
|
||||||
|
btn.addEventListener("click", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const modal = document.getElementById("trynowModal");
|
||||||
|
if (modal) {
|
||||||
|
modal.style.display = "flex";
|
||||||
|
// Reset modal state
|
||||||
|
const form = document.getElementById("trynowForm");
|
||||||
|
const confirmation = document.getElementById("trynowConfirmation");
|
||||||
|
if (form && confirmation) {
|
||||||
|
form.style.display = "flex";
|
||||||
|
confirmation.style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
tryNow_createModal();
|
||||||
|
tryNow_handleFormSubmit();
|
||||||
|
tryNow_attachButtons();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
171
public/widget-signup/widget.js
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
(function() {
|
||||||
|
console.log("WIDGET COOL")
|
||||||
|
const currentScript = document.currentScript;
|
||||||
|
const affiliateFromAttr = currentScript.getAttribute("data-affiliate");
|
||||||
|
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const affiliateFromURL = params.get("affiliate");
|
||||||
|
|
||||||
|
const affiliateCode = affiliateFromURL || affiliateFromAttr || "None";
|
||||||
|
|
||||||
|
const container = document.getElementById("my-signup-widget");
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
const shadow = container.attachShadow({ mode: "open" });
|
||||||
|
|
||||||
|
const styles = `
|
||||||
|
:host {
|
||||||
|
all: initial;
|
||||||
|
font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Inter,Arial,sans-serif;
|
||||||
|
display: block;
|
||||||
|
max-width: 420px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: linear-gradient(135deg,#ffffff 0%,#f7fafc 60%);
|
||||||
|
border: 1px solid #e6e8eb;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow: 0 6px 20px rgba(16,24,40,.08);
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.header { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
|
||||||
|
.icon { width: 36px; height: 36px; border-radius: 12px;
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
font-weight: 700; color: #fff;
|
||||||
|
}
|
||||||
|
.title { font-size: 18px; line-height: 1.2; font-weight: 800; color: #0f172a; }
|
||||||
|
.subtitle { font-size: 13px; color: #475569; }
|
||||||
|
label, .label { display: block; font-size: 12px; color: #334155; font-weight: 600; margin: 12px 0 6px; }
|
||||||
|
|
||||||
|
.options { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; }
|
||||||
|
.option { flex: 1; display: flex; align-items: center; gap: 8px;
|
||||||
|
border: 1px solid #cbd5e1; border-radius: 10px; padding: 10px 12px;
|
||||||
|
cursor: pointer; background: #fff;
|
||||||
|
}
|
||||||
|
input[type="radio"] { accent-color: #3b82f6; margin: 0; }
|
||||||
|
|
||||||
|
select, input[type="email"], .affiliate-display {
|
||||||
|
width: 100%;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #0f172a;
|
||||||
|
outline: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.affiliate-display { background: #f8fafc; }
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin-top: 16px;
|
||||||
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 800;
|
||||||
|
background: linear-gradient(135deg,#22c55e,#3b82f6);
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 8px 18px rgba(37,99,235,.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footnote { margin-top: 10px; font-size: 11px; color: #64748b; text-align: center; }
|
||||||
|
|
||||||
|
.status {
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #0f172a;
|
||||||
|
background: linear-gradient(135deg,#f0f9ff,#e0f2fe);
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
border-radius: 12px;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 0 4px 12px rgba(16,24,40,.08);
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
.status.success { background: linear-gradient(135deg,#d1fae5,#a7f3d0); color: #065f46; }
|
||||||
|
.status.error { background: linear-gradient(135deg,#fee2e2,#fecaca); color: #991b1b; }
|
||||||
|
`;
|
||||||
|
|
||||||
|
const html = `
|
||||||
|
<form class="card">
|
||||||
|
<div class="header">
|
||||||
|
<img class="icon" src="https://sp01.odoo4projects.com/hugo/live/4.svg">
|
||||||
|
<div>
|
||||||
|
<div class="title">Try Managed ODOO or n8n - 4 weeks Free</div>
|
||||||
|
<div class="subtitle">Full-featured 4-week trial. No credit card required.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="label">Product</div>
|
||||||
|
<div class="options">
|
||||||
|
<label class="option">
|
||||||
|
<input type="radio" name="product" value="odoo_19" required checked>
|
||||||
|
<span>ODOO</span>
|
||||||
|
</label>
|
||||||
|
<label class="option">
|
||||||
|
<input type="radio" name="product" value="N8N" required>
|
||||||
|
<span>N8N</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<label for="location">Location</label>
|
||||||
|
<select id="location" name="location" required>
|
||||||
|
<option value="" disabled>Select a region</option>
|
||||||
|
<option value="manchester">UK, Manchester</option>
|
||||||
|
<option value="boston">US, Boston</option>
|
||||||
|
<option value="mumbai">IN, Mumbai</option>
|
||||||
|
<option value="saopaulo">BR, Sao Paulo</option>
|
||||||
|
<option value="Meppel">NL, Meppel</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<label for="email">Work Email</label>
|
||||||
|
<input id="email" name="email" type="email" required placeholder="you@company.com">
|
||||||
|
|
||||||
|
<input type="hidden" name="affiliate_code" value="${affiliateCode}">
|
||||||
|
|
||||||
|
<button type="submit" class="plausible-event-name=Trial">Start 4-Week Free Trial</button>
|
||||||
|
|
||||||
|
<div class="footnote">
|
||||||
|
By submitting, you agree to the T&C of ODOO4projects.
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="status" class="status" style="display:none;"></div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
shadow.innerHTML = `<style>${styles}</style>${html}`;
|
||||||
|
|
||||||
|
const form = shadow.querySelector("form");
|
||||||
|
const statusEl = shadow.getElementById("status");
|
||||||
|
|
||||||
|
form.addEventListener("submit", async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
statusEl.style.display = "block";
|
||||||
|
statusEl.textContent = "Submitting...";
|
||||||
|
statusEl.className = "status";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const formData = new FormData(form);
|
||||||
|
const res = await fetch("https://002-001-5dd6e535-4d1c-46bc-9bd9-42ad4bc5f082.odoo4projects.com/webhook/c25169c6-4234-4b47-8e74-612b9539da0a", {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
const text = await res.text();
|
||||||
|
|
||||||
|
// Hide the form
|
||||||
|
form.style.display = "none";
|
||||||
|
|
||||||
|
// Show the webhook response nicely
|
||||||
|
statusEl.textContent = text;
|
||||||
|
statusEl.className = "status success";
|
||||||
|
} catch (err) {
|
||||||
|
statusEl.textContent = "❌ Failed to submit. Please try again.";
|
||||||
|
statusEl.className = "status error";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
37
public/widget/box/index.html
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Order Status Wizard</title>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<ul class="wizard">
|
||||||
|
<li class="open">
|
||||||
|
<div class="header">
|
||||||
|
<i class="fa-solid fa-signature"></i>
|
||||||
|
<span class="title">Name</span>
|
||||||
|
</div>
|
||||||
|
<div class="text">Open</div>
|
||||||
|
</li>
|
||||||
|
<li class="done">
|
||||||
|
<div class="header">
|
||||||
|
<i class="fa-solid fa-envelope"></i>
|
||||||
|
<span class="title">Email</span>
|
||||||
|
</div>
|
||||||
|
<div class="text">deraa@fewew.de</div>
|
||||||
|
</li>
|
||||||
|
<li class="done">
|
||||||
|
<div class="header">
|
||||||
|
<i class="fa-solid fa-cart-shopping"></i>
|
||||||
|
<span class="title">Product</span>
|
||||||
|
</div>
|
||||||
|
<div class="text">3 Hours</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
69
public/widget/box/styles.css
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard li {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-right: 2px solid #fff;
|
||||||
|
color: white;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard li:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard .header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detail text section */
|
||||||
|
.wizard .text {
|
||||||
|
padding: 20px 10px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DARK GREY: Open */
|
||||||
|
.wizard li.open {
|
||||||
|
background-color: #7f8c8d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard li.open .header {
|
||||||
|
background-color: #5d6d7e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DARK GREEN: Done */
|
||||||
|
.wizard li.done {
|
||||||
|
background-color: #1e8449;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard li.done .header {
|
||||||
|
background-color: #145a32;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard i {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
270
public/widget/custom/brandize.css
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
/* cw.css */
|
||||||
|
|
||||||
|
/* Container */
|
||||||
|
#cw-chatToggle {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 24px;
|
||||||
|
right: 24px;
|
||||||
|
color: white;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-radius: 25px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
z-index: 100000;
|
||||||
|
border: none;
|
||||||
|
user-select: none;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
#cw-chatToggle:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
#cw-chatToggle div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
#cw-chatToggle img {
|
||||||
|
image-rendering: pixelated;
|
||||||
|
image-rendering: optimizeQuality;
|
||||||
|
image-rendering: -webkit-optimize-contrast; /* Chrome */
|
||||||
|
image-rendering: crisp-edges; /* Fallback */
|
||||||
|
}
|
||||||
|
#cw-chatToggle span.text-sm {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.875rem; /* 14px */
|
||||||
|
}
|
||||||
|
#cw-chatToggle span.text-xs {
|
||||||
|
font-size: 0.75rem; /* 12px */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chat widget container */
|
||||||
|
#cw-chatWidget {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 100px;
|
||||||
|
right: 24px;
|
||||||
|
width: 500px;
|
||||||
|
max-height: 70vh;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 12px;
|
||||||
|
flex-direction: column;
|
||||||
|
z-index: 100000;
|
||||||
|
font-family: system-ui, sans-serif;
|
||||||
|
}
|
||||||
|
#cw-chatWidget.active {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logo container */
|
||||||
|
#cw-chatWidget .logo-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 16px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
#cw-chatWidget .logo-container img {
|
||||||
|
height: 60px;
|
||||||
|
user-select: none;
|
||||||
|
image-rendering: optimizeQuality;
|
||||||
|
image-rendering: pixelated;
|
||||||
|
image-rendering: -webkit-optimize-contrast; /* Chrome */
|
||||||
|
image-rendering: crisp-edges; /* Fallback */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
#cw-status {
|
||||||
|
padding: 10px 10px;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
max-height: 0;
|
||||||
|
transition: max-height 0.5s ease-in-out, padding 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cw-chatWidget .header {
|
||||||
|
background-color: #0070c0;
|
||||||
|
color: white;
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: center;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Messages container */
|
||||||
|
#cw-chatMessages {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 16px;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
user-select: text;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chat form */
|
||||||
|
#cw-chatForm {
|
||||||
|
display: flex;
|
||||||
|
margin: 0px;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
#cw-chatInput {
|
||||||
|
flex: 1;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 20px;
|
||||||
|
font-size: 1rem;
|
||||||
|
outline-offset: 2px;
|
||||||
|
border-radius: 0 0 0 12px;
|
||||||
|
}
|
||||||
|
#cw-chatInput:focus {
|
||||||
|
outline: 0px solid #0070c0;
|
||||||
|
}
|
||||||
|
#cw-chatForm button {
|
||||||
|
background-color: #0070c0;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
padding: 0 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: 600;
|
||||||
|
border-radius: 0 0 12px 0;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
#cw-chatForm button:hover {
|
||||||
|
background-color: #005a9e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Message bubbles */
|
||||||
|
.cw-message {
|
||||||
|
max-width: 75%;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
.cw-message.user {
|
||||||
|
background-color: #DCF8C6;
|
||||||
|
color: #333;
|
||||||
|
margin-left: auto;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.cw-message.bot {
|
||||||
|
background-color: #E0E0E0;
|
||||||
|
color: #333;
|
||||||
|
margin-right: auto;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 12px 24px;
|
||||||
|
background-color: transparent;
|
||||||
|
color: inherit;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 0px;
|
||||||
|
font-size: 16px;
|
||||||
|
border: none;
|
||||||
|
font-weight: bold;
|
||||||
|
transition: background-color 0.3s ease, box-shadow 0.3s ease;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 10%;
|
||||||
|
transform: translateY(-50%)
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:active {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Headline above the wizard */
|
||||||
|
.wizard-headline {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 20px 0;
|
||||||
|
background-color: #f8f9f9;
|
||||||
|
color: #2c3e50;
|
||||||
|
border-bottom: 2px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main wizard container */
|
||||||
|
.wizard {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Each step box */
|
||||||
|
.wizard li {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-right: 2px solid #fff;
|
||||||
|
color: white;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard li:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header inside each box (icon + label) */
|
||||||
|
.wizard .header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detail text area inside the box */
|
||||||
|
.wizard .text {
|
||||||
|
padding: 20px 10px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DARK GREY: Open */
|
||||||
|
.wizard li.open {
|
||||||
|
background-color: #7f8c8d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard li.open .header {
|
||||||
|
background-color: #5d6d7e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DARK GREEN: Done */
|
||||||
|
.wizard li.done {
|
||||||
|
background-color: #1e8449;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard li.done .header {
|
||||||
|
background-color: #145a32;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Icon style */
|
||||||
|
.wizard i {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
62
public/widget/custom/brandize.js
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import { Conversation } from 'https://cdn.skypack.dev/@elevenlabs/client';
|
||||||
|
|
||||||
|
let conversation = null;
|
||||||
|
let inCall = false;
|
||||||
|
|
||||||
|
document.addEventListener('JSsucks', () => {
|
||||||
|
|
||||||
|
const callBtn = document.getElementById('callBtn');
|
||||||
|
|
||||||
|
callBtn.addEventListener('click', async () => {
|
||||||
|
if (!inCall) {
|
||||||
|
console.log('Requesting microphone access...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await navigator.mediaDevices.getUserMedia({ audio: true });
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Microphone access denied.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Connecting to agent...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
conversation = await Conversation.startSession({
|
||||||
|
agentId: 'agent_01jx2xm2w4exwvjhbq52js687f',
|
||||||
|
connectionType: 'websocket',
|
||||||
|
onConnect: () => {
|
||||||
|
console.log('✅ Connected to AI Agent!');
|
||||||
|
callBtn.style.color = 'red';
|
||||||
|
inCall = true;
|
||||||
|
},
|
||||||
|
onDisconnect: () => {
|
||||||
|
console.log('🔌 Disconnected.');
|
||||||
|
callBtn.style.color = 'grey';
|
||||||
|
inCall = false;
|
||||||
|
},
|
||||||
|
onError: (err) => {
|
||||||
|
console.log(`❌ Error: ${err.message || err}`);
|
||||||
|
},
|
||||||
|
onMessage: (msg) => {
|
||||||
|
console.log('Agent:', msg);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Failed to start session.');
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Hanging up...');
|
||||||
|
try {
|
||||||
|
await conversation.endSession();
|
||||||
|
conversation = null;
|
||||||
|
inCall = false;
|
||||||
|
callBtn.style.color = 'grey';
|
||||||
|
console.log('✅ Call ended.');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error ending the call:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
6
public/widget/custom/brandize.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"api": "https://002-001-433cd554-0d64-4834-8500-3aebea781003.odoo4projects.com/webhook/81742473-b50b-4845-a5f9-916d9fe60876/chat",
|
||||||
|
"preamble": "Welcome to Brandize",
|
||||||
|
"widgetHTML": "<button id='cw-chatToggle' aria-label='Toggle chat widget' type='button'>\n <img height='50px' src='widget/custom/brandize.svg' alt='Logo'></button>\n<div id='cw-chatWidget' style='display: none;' role='region' aria-live='polite' aria-label='Chat widget'>\n <div class='logo-container'><img src='widget/custom/brandize.svg' alt='Logo' /><button id='callBtn' class='button'>📞</button></div>\n <div class='header'>Support</div>\n <div id='cw-status' style='transition: all 0.3s ease; overflow: hidden;'></div>\n <div id='cw-chatMessages' style='max-height: 200px; overflow-y: auto; padding: 10px;'></div>\n <form id='cw-chatForm' autocomplete='off'>\n <input type='text' id='cw-chatInput' placeholder='Type your message...' required autocomplete='off' />\n <button type='submit'>Send</button>\n </form>\n</div>"
|
||||||
|
}
|
||||||
|
|
||||||
96
public/widget/custom/brandize.svg
Normal file
|
After Width: | Height: | Size: 36 KiB |
268
public/widget/custom/od8n.css
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
/* cw.css */
|
||||||
|
|
||||||
|
/* Container */
|
||||||
|
#cw-chatToggle {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 24px;
|
||||||
|
right: 24px;
|
||||||
|
color: white;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-radius: 25px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
z-index: 100000;
|
||||||
|
border: none;
|
||||||
|
user-select: none;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
width: 100px;
|
||||||
|
height: 50px;
|
||||||
|
box-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px, rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
|
||||||
|
}
|
||||||
|
#cw-chatToggle:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
#cw-chatToggle div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
#cw-chatToggle img {
|
||||||
|
image-rendering: pixelated;
|
||||||
|
image-rendering: optimizeQuality;
|
||||||
|
image-rendering: -webkit-optimize-contrast; /* Chrome */
|
||||||
|
image-rendering: crisp-edges; /* Fallback */
|
||||||
|
}
|
||||||
|
#cw-chatToggle span.text-sm {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.875rem; /* 14px */
|
||||||
|
}
|
||||||
|
#cw-chatToggle span.text-xs {
|
||||||
|
font-size: 0.75rem; /* 12px */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chat widget container */
|
||||||
|
#cw-chatWidget {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 100px;
|
||||||
|
right: 24px;
|
||||||
|
width: 500px;
|
||||||
|
max-height: 70vh;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 12px;
|
||||||
|
flex-direction: column;
|
||||||
|
z-index: 100000;
|
||||||
|
font-family: system-ui, sans-serif;
|
||||||
|
}
|
||||||
|
#cw-chatWidget.active {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logo container */
|
||||||
|
#cw-chatWidget .logo-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 16px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
#cw-chatWidget .logo-container img {
|
||||||
|
height: 60px;
|
||||||
|
user-select: none;
|
||||||
|
image-rendering: optimizeQuality;
|
||||||
|
image-rendering: pixelated;
|
||||||
|
image-rendering: -webkit-optimize-contrast; /* Chrome */
|
||||||
|
image-rendering: crisp-edges; /* Fallback */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
#cw-status {
|
||||||
|
padding: 10px 10px;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
max-height: 0;
|
||||||
|
transition: max-height 0.5s ease-in-out, padding 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cw-chatWidget .header {
|
||||||
|
background-color: #0070c0;
|
||||||
|
color: white;
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: center;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Messages container */
|
||||||
|
#cw-chatMessages {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 16px;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
user-select: text;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chat form */
|
||||||
|
#cw-chatForm {
|
||||||
|
display: flex;
|
||||||
|
margin: 0px;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
#cw-chatInput {
|
||||||
|
flex: 1;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 20px;
|
||||||
|
font-size: 1rem;
|
||||||
|
outline-offset: 2px;
|
||||||
|
border-radius: 0 0 0 12px;
|
||||||
|
}
|
||||||
|
#cw-chatInput:focus {
|
||||||
|
outline: 0px solid #0070c0;
|
||||||
|
}
|
||||||
|
#cw-chatForm button {
|
||||||
|
background-color: #0070c0;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
padding: 0 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: 600;
|
||||||
|
border-radius: 0 0 12px 0;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
#cw-chatForm button:hover {
|
||||||
|
background-color: #005a9e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Message bubbles */
|
||||||
|
.cw-message {
|
||||||
|
max-width: 75%;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
.cw-message.user {
|
||||||
|
background-color: #DCF8C6;
|
||||||
|
color: #333;
|
||||||
|
margin-left: auto;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.cw-message.bot {
|
||||||
|
background-color: #E0E0E0;
|
||||||
|
color: #333;
|
||||||
|
margin-right: auto;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 12px 24px;
|
||||||
|
background-color: #4CAF50; /* Green */
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
transition: background-color 0.3s ease, box-shadow 0.3s ease;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
box-shadow: 0 6px 10px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:active {
|
||||||
|
background-color: #3e8e41;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Headline above the wizard */
|
||||||
|
.wizard-headline {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 20px 0;
|
||||||
|
background-color: #f8f9f9;
|
||||||
|
color: #2c3e50;
|
||||||
|
border-bottom: 2px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main wizard container */
|
||||||
|
.wizard {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Each step box */
|
||||||
|
.wizard li {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-right: 2px solid #fff;
|
||||||
|
color: white;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard li:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header inside each box (icon + label) */
|
||||||
|
.wizard .header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detail text area inside the box */
|
||||||
|
.wizard .text {
|
||||||
|
padding: 20px 10px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DARK GREY: Open */
|
||||||
|
.wizard li.open {
|
||||||
|
background-color: #7f8c8d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard li.open .header {
|
||||||
|
background-color: #5d6d7e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DARK GREEN: Done */
|
||||||
|
.wizard li.done {
|
||||||
|
background-color: #1e8449;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard li.done .header {
|
||||||
|
background-color: #145a32;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Icon style */
|
||||||
|
.wizard i {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
0
public/widget/custom/od8n.js
Normal file
6
public/widget/custom/od8n.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"api": "https://ai.odoo4projects.com/webhook/81742473-b50b-4845-a5f9-916d9fe60876/chat",
|
||||||
|
"preamble": "Welcome to OD8N. We like to help you assisting your order as well as answering FAQs about our service",
|
||||||
|
"widgetHTML": "<button id='cw-chatToggle' aria-label='Toggle chat widget' type='button' class='plausible-event-name=OpenChat'>\n <img height='50px'src='logo.svg' alt='Logo'></button>\n<div id='cw-chatWidget' style='display: none;' role='region' aria-live='polite' aria-label='Chat widget'>\n <div class='logo-container'><img src='logo.svg' alt='Logo' /></div>\n <div class='header'>Support</div>\n <div id='cw-status' style='transition: all 0.3s ease; overflow: hidden;'></div>\n <div id='cw-chatMessages' style='max-height: 200px; overflow-y: auto; padding: 10px;'></div>\n <form id='cw-chatForm' autocomplete='off'>\n <input type='text' id='cw-chatInput' placeholder='Type your message...' required autocomplete='off' />\n <button type='submit'>Send</button>\n </form>\n</div>"
|
||||||
|
}
|
||||||
|
|
||||||
105
public/widget/widget.js
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(configUrl);
|
||||||
|
if (!response.ok) throw new Error(`Config not found at ${configUrl}`);
|
||||||
|
|
||||||
|
const config = await response.json();
|
||||||
|
const { widgetHTML, preamble, api } = config;
|
||||||
|
|
||||||
|
if (!widgetHTML || !api) {
|
||||||
|
console.error('Invalid config format. Expected widgetHTML and api.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inject HTML
|
||||||
|
document.body.insertAdjacentHTML('beforeend', widgetHTML);
|
||||||
|
console.log("HERE!")
|
||||||
|
document.dispatchEvent(new CustomEvent('JSsucks'));
|
||||||
|
// DOM references
|
||||||
|
const chatToggle = document.getElementById('cw-chatToggle');
|
||||||
|
const chatWidget = document.getElementById('cw-chatWidget');
|
||||||
|
const chatForm = document.getElementById('cw-chatForm');
|
||||||
|
const chatInput = document.getElementById('cw-chatInput');
|
||||||
|
const chatMessages = document.getElementById('cw-chatMessages');
|
||||||
|
const statusDiv = document.getElementById('cw-status');
|
||||||
|
|
||||||
|
const sessionId = crypto.randomUUID();
|
||||||
|
let chatOpened = false;
|
||||||
|
|
||||||
|
// Append a message to the chat
|
||||||
|
function appendMessage(text, sender) {
|
||||||
|
const msg = document.createElement('div');
|
||||||
|
msg.classList.add('cw-message', sender === 'user' ? 'user' : 'bot');
|
||||||
|
msg.innerHTML = text;
|
||||||
|
chatMessages.appendChild(msg);
|
||||||
|
chatMessages.scrollTop = chatMessages.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Centralized function to send a message
|
||||||
|
async function sendMessageToBot(messageText) {
|
||||||
|
console.log(messageText)
|
||||||
|
chatWidget.style.display = 'block';
|
||||||
|
appendMessage(messageText, 'user');
|
||||||
|
chatInput.value = '';
|
||||||
|
chatInput.focus();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(api, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
action: 'sendMessage',
|
||||||
|
sessionId,
|
||||||
|
chatInput: messageText
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (data.status) {
|
||||||
|
statusDiv.innerHTML = data.status;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
statusDiv.style.padding = '10px';
|
||||||
|
statusDiv.style.maxHeight = statusDiv.scrollHeight + 'px';
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
statusDiv.style.maxHeight = '0';
|
||||||
|
statusDiv.style.padding = '0 10px';
|
||||||
|
}
|
||||||
|
|
||||||
|
appendMessage(data.output, 'bot');
|
||||||
|
} catch (error) {
|
||||||
|
appendMessage('Fehler beim Verbinden mit dem Server. Bitte versuchen Sie es später erneut.', 'bot');
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.sendMessageToBot = sendMessageToBot;
|
||||||
|
// Toggle chat widget
|
||||||
|
chatToggle.addEventListener('click', () => {
|
||||||
|
const isVisible = chatWidget.style.display === 'block';
|
||||||
|
chatWidget.style.display = isVisible ? 'none' : 'block';
|
||||||
|
|
||||||
|
if (!isVisible && !chatOpened) {
|
||||||
|
appendMessage(preamble, 'bot');
|
||||||
|
chatOpened = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Form submission
|
||||||
|
chatForm.addEventListener('submit', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const input = chatInput.value.trim();
|
||||||
|
if (input) {
|
||||||
|
sendMessageToBot(input);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Attach buy button listeners
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to initialize chat widget:', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||