Add the chat assistant to your store with a single line of code
The Emporiqa chat widget is a lightweight chat assistant that you can embed on your e-commerce store. It provides:
One line of code: The widget is embedded with a single script tag. No complex setup or build process required.
Platform Support: We have ready-to-use integrations for Drupal Commerce, WooCommerce, Sylius, Magento 2, PrestaShop, and Shopware. The widget works with any website or e-commerce platform.
Each store has a unique Store ID that identifies it. To find your Store ID and embed code:
Quick Tip: The embed code is ready to use - just copy and paste it into your store's HTML.
Important: Before embedding the widget, ensure you have sent your product and page data via webhooks. The widget won't function properly without product data.
Add this single line of code to your website, just before the closing </body> tag:
<script async crossorigin="anonymous" src="https://emporiqa.com/chat/embed/?store_id=YOUR_STORE_ID&language=en"></script>
Replace YOUR_STORE_ID with your actual Store ID, and en with your store's language code (e.g., en, de, fr, pt-br, zh-cn). Both 2-letter codes and full regional codes are accepted. Codes are case-insensitive: EN, en-US, and en-us all work.
Cross-language support: The language parameter sets the language of your store content (products, pages). If a customer writes in a different language, the salesperson automatically detects it and responds in their language while searching your content in its original language.
Required Parameters: Both store_id and language are required. The widget will not load without them.
You can add optional parameters to control currency display and sales channel filtering:
<script async crossorigin="anonymous" src="https://emporiqa.com/chat/embed/?store_id=YOUR_STORE_ID&language=en¤cy=EUR&channel=b2b"></script>
| Parameter | Required | Description |
|---|---|---|
store_id |
Yes | Your store's unique identifier |
language |
Yes | Language code for the widget (e.g., en, de, pt-br). Determines the display language and which product translations to search. |
currency |
No | ISO 4217 currency code (e.g., EUR, USD). When set, product prices are shown in this currency. Products without a matching price entry use the first available price as fallback. |
channel |
No | Sales channel identifier (e.g., b2b, retail). When set, only shows products and pages from this channel plus store-wide items. |
user_id |
No | HMAC-signed customer token for order tracking. See User Identification. |
<!DOCTYPE html>
<html>
<head>
<title>My Store</title>
</head>
<body>
<!-- Your store content -->
<!-- Emporiqa Widget - place before </body> -->
<script async crossorigin="anonymous" src="https://emporiqa.com/chat/embed/?store_id=ABC123xyz...&language=en"></script>
</body>
</html>
The script automatically creates a floating chat button in the corner of your page. Customers can click it to open the chat widget.
You can optionally pass a user_id parameter to track conversations across sessions and devices. This is useful for logged-in customers. If you use order tracking, the user ID is forwarded to your order tracking API so you can restrict results to that customer's orders.
The user_id parameter must be a signed token generated server-side using your connection secret. This prevents customers from forging another user's identity.
The token is composed of two parts separated by a dot: a Base64url-encoded JSON payload and an HMAC-SHA256 signature.
base64url({"uid":"CUSTOMER_ID","ts":UNIX_TIMESTAMP}).hmac_sha256_hex(payload, webhook_secret)
uid - Any string that uniquely identifies the customer (customer ID, email, account number)ts - Unix timestamp when the token was created. Tokens expire after 90 days.The token must be generated on your server - never expose the connection secret to the browser.
function emporiqa_generate_user_token(string $userId, string $webhookSecret): string
{
$payload = json_encode(['uid' => $userId, 'ts' => time()], JSON_UNESCAPED_SLASHES);
$encodedPayload = rtrim(strtr(base64_encode($payload), '+/', '-_'), '=');
$signature = hash_hmac('sha256', $encodedPayload, $webhookSecret);
return $encodedPayload . '.' . $signature;
}
import base64, hashlib, hmac, json, time
def emporiqa_generate_user_token(user_id: str, webhook_secret: str) -> str:
payload = json.dumps({"uid": user_id, "ts": int(time.time())}, separators=(",", ":")).encode()
encoded_payload = base64.urlsafe_b64encode(payload).decode().rstrip("=")
signature = hmac.new(webhook_secret.encode(), encoded_payload.encode(), hashlib.sha256).hexdigest()
return f"{encoded_payload}.{signature}"
<script async crossorigin="anonymous" src="https://emporiqa.com/chat/embed/?store_id=YOUR_STORE_ID&language=en&user_id=TOKEN_HERE"></script>
$params = ['store_id' => $store_id, 'language' => $language];
if ($user->isAuthenticated()) {
$params['user_id'] = emporiqa_generate_user_token((string) $user->id(), $webhook_secret);
}
$url = 'https://emporiqa.com/chat/embed/?' . http_build_query($params);
Important: Never expose your connection secret in client-side code. The token must be generated on the server and injected into the page template.
Tip: If you don't need user identification, simply omit the user_id parameter. The chat widget works without it. The customer's user ID will not be available for order tracking in that case.
Customize the widget appearance through your Emporiqa dashboard. No code changes required!
| Option | Description | Default |
|---|---|---|
| Custom CSS | Custom styles for the widget (see below) | Default theme |
| Position | Widget button location | Bottom Right |
| Widget Title | Header text (supports {store_name}) | {store_name} |
| Greeting Message | Initial welcome message | Hi! How can I help you today? |
| Allowed Domains | Restrict where widget can be embedded | All domains |
Use the Custom CSS field to fully customize the chat widget's appearance. Your CSS is injected into the widget iframe and can override any styles.
The widget uses CSS variables for colors. Override them in the :root selector:
:root {
--primary-color: #1A73E8; /* Send button and accent color */
--secondary-color: #1669D4; /* Hover states */
}
:root {
--primary-color: #E91E63; /* Pink brand color */
--secondary-color: #C2185B; /* Darker pink for hover */
}
/* Additional customizations */
.btn-primary {
border-radius: 4px; /* Square corners */
}
You can configure different titles and messages for each language in your dashboard. The widget automatically detects the customer's language.
The widget automatically adapts to screen size. On screens smaller than 850px, it switches to mobile mode.
Restrict where your widget can be embedded by configuring allowed domains in your dashboard. This prevents unauthorized sites from using your widget.
Example: If you set allowed domains to mystore.com, shop.mystore.com, the widget will only work on those domains.
The widget uses time-limited, HMAC-signed tokens for API authentication. This prevents abuse and ensures requests come from legitimate widget instances.
Built-in rate limiting protects against abuse:
If cart operations are enabled for your store, the widget delegates cart actions (add, remove, update, clear, view, checkout) to a JavaScript function on your page. The plugins for Drupal Commerce, WooCommerce, Sylius, and Magento 2 implement this automatically.
For custom platforms, register EmporiqaCartHandler before the widget loads:
window.EmporiqaCartHandler = async function({ action, items }) {
const item = items?.[0];
if (action === 'add') {
const res = await fetch('/api/cart/add', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
product_id: item.product_id,
variation_id: item.variation_id,
quantity: item.quantity
})
});
return await res.json();
}
if (action === 'view') {
const res = await fetch('/api/cart');
return await res.json();
}
if (action === 'checkout') {
return { success: true, checkoutUrl: '/checkout' };
}
// handle remove, update, clear similarly
};
Every handler call must resolve with this structure:
{
"success": true,
"checkoutUrl": "/checkout/2",
"cart": {
"items": [
{
"product_id": "257",
"variation_id": "1097",
"name": "iPhone 14 - Midnight, 128GB",
"quantity": 1,
"unit_price": 699.00,
"image_url": "https://store.com/images/iphone-14.jpg",
"product_url": "https://store.com/product/iphone-14"
}
],
"item_count": 3,
"total": 1397.00,
"currency": "USD"
}
}
| Field | Type | Description |
|---|---|---|
success |
boolean | Whether the operation succeeded |
checkoutUrl |
string | URL for the checkout page (used by the "Proceed to checkout" button) |
cart.items[].unit_price |
number | Price per single unit as a plain number (e.g. 699.00, not "$699.00") |
cart.item_count |
integer | Total quantity across all items |
cart.total |
number | Cart total as a plain number |
cart.currency |
string | ISO 4217 currency code (e.g. USD, EUR) |
Important: All prices must be plain numbers, not formatted strings. 699.00 is correct. "$699.00", "699.000000", and "$699.00" are all wrong. The widget handles formatting based on the product's currency and the widget's language setting.
</body>defer attributeBefore going live, test your widget thoroughly:
Our team is here to help with your integration. Whether you need assistance with webhooks, widget embedding, or troubleshooting, just reach out.
Contact Support