Documentation
Technical guides for your integration – multi-channel, widgets, API and Shopware.
Multi-channel / Locations
With the locations feature you can collect and analyse reviews separately by branch, sales channel or region. Each location has its own name, slug, an optional domain and a default language.
Plan limits: FREE = 1 location, STARTER = 2, PRO = 10, ENTERPRISE = 100
When should you use locations?
Locations are ideal if you:
- run several branches or offices
- have different online shops or domains
- want to separate reviews by region or department
- want to embed a separate widget per location on the respective website
Managing locations
Under Settings → Locations you can create, edit and delete locations.
- Name: Display name (e.g. “London Soho branch”)
- Slug: Unique identifier, generated automatically from the name
- Domain: Optional – the website URL of the location
- Language: Default language for this location
- Default location: The location marked as default is used for new reviews without an explicit assignment
When you delete a location, all assigned reviews are kept – they only lose their location assignment.
How are reviews assigned to a location?
There are three ways:
- Automatically via the review form: If your company has several locations, a dropdown “Which location would you like to review?” appears on the profile page – the customer selects the location.
- Via review invitations: When sending an invitation you can specify the location. The review is then assigned automatically.
- Via API: Pass the
locationIdwhen creating a review.
Widgets per location
In the widget builder under Settings → Location filter you can restrict a widget to a specific location. The widget then only shows reviews of that location.
For example, the website of your London branch can show only the London reviews and the Manchester page only the Manchester ones.
API reference
Create a location:
{
"name": "Online Shop UK",
"slug": "shop-uk",
"domain": "https://www.my-shop.co.uk",
"language": "en"
}Create a review assigned to a location:
{
"companyId": "...",
"locationId": "clx...",
"rating": 5,
"content": "Great service!",
"reviewerName": "John Smith"
}Filter reviews by location:
// Returns only reviews of the given location
// Without locationId all reviews are returnedCreate a widget with a location filter:
{
"companyId": "...",
"locationId": "clx...",
"name": "Widget London branch",
"type": "CAROUSEL",
"config": { "maxReviews": 5 }
}Multilingual widgets
The embedded widget supports 5 languages: Deutsch, English, Français, Español and Italiano. All UI texts (buttons, time labels, form fields) are shown automatically in the detected language.
Language detection (priority)
data-langattribute on the widget container (explicit)localefield in the widget configuration (dashboard)document.documentElement.lang(HTML language of the page)- Fallback:
de
Option 1: Explicitly via HTML attribute
Ideal for multilingual shops where the language of each page is known:
<!-- German widget -->
<div data-zoom-widget="WIDGET_ID" data-lang="de"></div>
<!-- English widget -->
<div data-zoom-widget="WIDGET_ID" data-lang="en"></div>
<!-- French widget -->
<div data-zoom-widget="WIDGET_ID" data-lang="fr"></div>
<script src="https://zoom.reviews/widget.js" async></script>Option 2: Automatically via the shop language
If your shop template sets the lang attribute on the <html> tag correctly, the widget detects the language automatically:
<html lang="fr">
...
<div data-zoom-widget="WIDGET_ID"></div>
<script src="https://zoom.reviews/widget.js" async></script>
</html>Option 3: Via dashboard configuration
Under Widgets → Edit → Settings you can set a fixed language per widget. This is useful if you create a separate widget for each shop or language channel.
Shopware / Twig example
{# In your theme template #}
<div data-zoom-widget="WIDGET_ID"
data-lang="{{ app.request.locale[:2] }}"></div>
<script src="https://zoom.reviews/widget.js" async></script>Integrity check (SRI)
If your security policies require it, you can embed a fixed version with Subresource Integrity instead of the self-updating widget.js. Before executing it, the browser then checks via hash that the script exactly matches the published version, and blocks it otherwise.
<div data-zoom-widget="WIDGET_ID"></div>
<script src="https://zoom.reviews/widget/v1.js"
integrity="sha384-b+jQQNJZZso+gHv6OrEFQWf3CnUlnPR95LwStglzZ9EDIhLlhwIEMunoVr+X1GKT"
crossorigin="anonymous" async></script>Fixed versions do not receive automatic updates or bug fixes. When we release a new version, you need to replace the snippet yourself. We notify you by email about changes so that you can replace the snippet in time. You can always find the current snippet under Widgets → Embed code.
Review invitations (post-purchase)
Automatically send review invitations to your customers after a purchase. The emails are multilingual (DE/EN/FR/ES/IT) and contain a personalised link.
Available from: Pro plan (100 invitations/day) · Enterprise (1,000 invitations/day)
Create a single invitation
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
{
"email": "customer@example.com",
"customerName": "John Smith",
"orderId": "ORD-10042",
"orderDate": "2026-07-28T14:30:00Z",
"locale": "en",
"locationId": "clx...",
"delayDays": 7
}| Parameter | Required | Description |
|---|---|---|
| Yes | Customer's email address | |
| customerName | Yes | Customer's name |
| orderId | No | Order number (for matching) |
| locale | No | Language of the email (de/en/fr/es/it) |
| locationId | No | Location ID for the assignment |
| delayDays | No | Delay in days (0 = immediately, default: 7) |
Batch invitations (up to 100 at once)
{
"invitations": [
{ "email": "a@example.com", "customerName": "Anna", "locale": "de" },
{ "email": "b@example.com", "customerName": "Bob", "locale": "en" },
{ "email": "c@example.com", "customerName": "Claire", "locale": "fr" }
]
}What the customer experiences
- The customer receives a personalised email with a review link
- The link opens your review page with the name pre-filled
- The review is automatically marked as verified (no captcha)
- The token can only be used once
List invitations
// Status: PENDING, SENT, OPENED, COMPLETED, EXPIREDOutgoing webhooks
Receive real-time notifications about new reviews and invitations. Webhooks are signed with HMAC-SHA256.
Enterprise plan only. Up to 10 webhook endpoints per company.
Available events
| Event | Description |
|---|---|
| review.created | New review submitted |
| review.approved | Review approved |
| review.rejected | Review rejected |
| invitation.sent | Invitation sent |
| invitation.completed | Invitation completed (review submitted) |
Create a webhook
{
"url": "https://your-server.com/webhooks/zoom-reviews",
"events": ["review.created", "review.approved"]
}The response contains a secret (shown only once!) used to verify the signature.
Payload format
// Headers:
// X-Webhook-Signature: <HMAC-SHA256 of body>
// X-Webhook-Event: review.created
// X-Webhook-Timestamp: 2026-07-29T18:30:00.000Z
{
"event": "review.created",
"data": {
"id": "clx...",
"rating": 5,
"reviewerName": "John Smith",
"source": "WIDGET",
"locationId": "clx..."
},
"timestamp": "2026-07-29T18:30:00.000Z"
}Verify the signature
const crypto = require('crypto');
function verifyWebhook(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}Management
Under Settings → Webhooks (coming soon) or via API:
GET /api/webhooks/outgoing— List all endpointsPATCH /api/webhooks/outgoing— Change URL/events/statusDELETE /api/webhooks/outgoing?id=...— Delete an endpoint
Shopware 6 integration
Automatic review invitations after order completion in your Shopware 6 shop. The integration automatically detects the order language and the sales channel.
Overview
Step 1
Configure the webhook URL in Shopware
Step 2
Choose a Flow Builder event
Step 3
Set delay & language
Method A: Shopware Flow Builder (recommended)
- In your Shopware admin, go to Settings → Flow Builder
- Create a new flow with the trigger
Order placedorOrder status changed → Completed - Add a Send HTTP request action
- Method:
POST - URL: your webhook URL (see integration settings)
- Content-Type:
application/json
Method B: Call the REST API directly
Alternatively, you can call the review invitation API directly from a custom plugin or app:
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
{
"email": "{{ order.orderCustomer.email }}",
"customerName": "{{ order.orderCustomer.firstName }} {{ order.orderCustomer.lastName }}",
"orderId": "{{ order.orderNumber }}",
"locale": "en",
"delayDays": 7
}Multi-shop / multi-channel
If you run several Shopware sales channels:
- Create one location per sales channel in Zoom.Reviews
- Pass the
locationIdin the API request - Reviews are then collected separately and shown per channel
Language detection
The Shopware integration automatically detects the order language from the order's locale field. Supported: de, en, fr, es, it. Falls back to the configured default language.
Embed the widget in your Shopware theme
{# Widget with automatic language detection #}
<div data-zoom-widget="WIDGET_ID"
data-lang="{{ app.request.locale[:2] }}">
</div>
<script src="https://zoom.reviews/widget.js" async></script>Tip: Create a separate widget with the corresponding locationId for each sales channel. That way each shop only shows its own reviews.
Ready to integrate?
Start for free and embed your first reviews in just a few minutes.