Multi-tenant analytics
Recommended model
Section titled “Recommended model”Advanced use-case note: this page 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.
For a shared-host product such as market.example.com, Pomelo recommends this
model:
| Concept | Role | Example |
|---|---|---|
site | Global analytics entity | market.example.com |
tenant | Shop or analytics group | demo-shop |
hostname / path | Routing context | market.example.com/demo-shop |
site_id stays the marketplace identity. tenant_id stays the stable shop
identity. tenant_slug is for routing and tenant_name is for display.
Variable names
Section titled “Variable names”| Surface | Variables |
|---|---|
| JavaScript SDK | tenantId, tenantSlug, tenantName, targetTenantId, targetTenantSlug, targetTenantName |
| Public API / wire | tenant_id, tenant_slug, tenant_name |
| Internal storage | group_type, group_id, group_slug, group_name, group_source |
Shop registry
Section titled “Shop registry”Your platform remains the source of truth for tenants and synchronizes that
registry into Pomelo. Pomelo then resolves tenant_slug -> tenant_id against
that registry.
Attribution follows this order:
- explicit
tenant_id - explicit
tenant_slug - first path segment, for example
/demo-shop - no tenant
The path fallback is useful for shop pages, but the registry stays canonical.
If an explicit tenant is provided but cannot be resolved, the event stays
unresolved and does not fall back to the path. The page filter is
therefore not a multi-tenant strategy.
See also: Multi-tenant guide.
Web SDK
Section titled “Web SDK”Set the current tenant
Section titled “Set the current tenant”<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>On tenant pages, replace the standard Pomelo tag with the single tenant-aware
tag shown here, or call setTenant() from your framework’s SDK-ready callback
on the same script. Do not load analytics.js twice. When this happens during
SDK startup, Pomelo applies the tenant context before replaying the buffered
startup pageview.
Startup and subsequent pageview, engagement, perf.*, and error.*
events then inherit that current tenant.
Target a shop from a global page
Section titled “Target a shop from a global page”window.pomelo?.track('boutique.contact_click', { action_id: 'shop:contact_click', targetTenantId: 'tenant_demo_shop', targetTenantSlug: 'demo-shop', targetTenantName: 'Demo Shop',});Return to marketplace-level tracking
Section titled “Return to marketplace-level tracking”window.pomelo?.clearTenant();Public API
Section titled “Public API”List tenants for a site
Section titled “List tenants for a site”curl -sS -G "https://api.pomeloanalytics.com/v1/tenants" \ -H "Authorization: Bearer $POMELO_API_TOKEN" \ --data-urlencode "site_id=site_marketplace"Query one shop
Section titled “Query one shop”curl -sS -G "https://api.pomeloanalytics.com/v1/metrics/timeseries" \ -H "Authorization: Bearer $POMELO_API_TOKEN" \ --data-urlencode "site_id=site_marketplace" \ --data-urlencode "tenant_id=tenant_demo_shop" \ --data-urlencode "metric=pageviews"Break down by shop
Section titled “Break down by shop”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"When dimension=tenant, each row uses the stable tenant_id as key. The
response also includes tenant_slug and tenant_name as display labels.
Tokens and security
Section titled “Tokens and security”Tokens can be restricted with:
allowedSiteIdsallowedTenantIds
When a token is restricted to tenants, always send tenant_id on analytics
queries.