Skip to content

Multi-tenant guide

Advanced use-case note: this guide documents customer-, account-, or shop-facing statistics. Multi-tenant is an organization and access model for statistics, not a collection level by itself. API examples require a plan with tenant API access enabled and a configuration compatible with that restitution level.

Use one Pomelo site for the shared product and one stable tenant_id for each shop, account, or workspace.

Example model:

FieldExample
Hostnamemarket.example.com
site_idsite_marketplace
tenant_idtenant_demo_shop
tenant_slugdemo-shop
tenant_nameDemo Shop

If all tenants live under one hostname, keep one Pomelo site for that hostname. Do not create one site per tenant unless each tenant has its own hostname or domain.

Install the standard Pomelo script for that site first:

<script
defer
src="https://cdn.pomeloanalytics.com/latest/analytics.js"
data-site-id="site_marketplace"
></script>

Before enabling tenant-level dashboards, synchronize a tenant registry into Pomelo from your own backend or control plane.

Rules:

  • tenant_id must stay stable over time
  • tenant_slug may change when routing changes
  • tenant_name is display metadata only

After the SDK has loaded, set the active tenant once on tenant pages and let page, engagement, performance, and error events inherit it. On tenant pages, do not load analytics.js twice: replace the standard tag from step 1 with one tenant-aware tag, and set tenant context from that tag’s onload callback. In an app framework, use the equivalent SDK-ready callback. During SDK startup, Pomelo applies that tenant context before replaying the buffered startup pageview.

<script
defer
src="https://cdn.pomeloanalytics.com/latest/analytics.js"
data-site-id="site_marketplace"
onload="window.pomelo?.setTenant({
tenantId: 'tenant_demo_shop',
tenantSlug: 'demo-shop',
tenantName: 'Demo Shop'
})"
></script>

When the user leaves the tenant context, clear it:

<script>
window.pomelo?.clearTenant();
</script>

4. Use target tenant fields for cross-tenant actions

Section titled “4. Use target tenant fields for cross-tenant actions”

From a shared landing page, search page, or directory page, attribute an action to a tenant explicitly:

window.pomelo?.track('shop.contact_click', {
action_id: 'shop:contact_click',
targetTenantId: 'tenant_demo_shop',
targetTenantSlug: 'demo-shop',
targetTenantName: 'Demo Shop',
});

If an explicit tenant cannot be resolved, Pomelo keeps the event unresolved. It does not silently reassign that event from the page path.

Global marketplace view:

Terminal window
curl -sS -G "https://api.pomeloanalytics.com/v1/reports/overview" \
-H "Authorization: Bearer $POMELO_API_TOKEN" \
--data-urlencode "site_id=site_marketplace" \
--data-urlencode "from=2026-02-01" \
--data-urlencode "to=2026-02-28"

Tenant view:

Terminal window
curl -sS -G "https://api.pomeloanalytics.com/v1/reports/overview" \
-H "Authorization: Bearer $POMELO_API_TOKEN" \
--data-urlencode "site_id=site_marketplace" \
--data-urlencode "tenant_id=tenant_demo_shop" \
--data-urlencode "from=2026-02-01" \
--data-urlencode "to=2026-02-28"

Tenant breakdown:

Terminal window
curl -sS -G "https://api.pomeloanalytics.com/v1/metrics/breakdown" \
-H "Authorization: Bearer $POMELO_API_TOKEN" \
--data-urlencode "site_id=site_marketplace" \
--data-urlencode "dimension=tenant" \
--data-urlencode "metric=pageviews"

For dimension=tenant, Pomelo returns:

  • key = tenant_id
  • tenant_id as the canonical identity
  • tenant_slug and tenant_name as current display labels from the registry

If a token is restricted with allowedTenantIds, always send tenant_id on analytics requests. Tenant-scoped access control is enforced on tenant_id, not on the page path or on tenant_slug.

Use GET /v1/tenants?site_id=... to list the active accessible tenants for a site before querying shop-level reports.

  • Use one shared site_id per shared hostname
  • Keep tenant_id stable and independent from routing
  • Synchronize the tenant registry before exposing tenant dashboards
  • Use setTenant() on tenant pages and targetTenant* on shared pages
  • Do not use the page filter as a tenant security boundary
  • Use tenant_slug and tenant_name only for display