Skip to content

Multi-tenant analytics

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.

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

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:

  1. explicit tenant_id
  2. explicit tenant_slug
  3. first path segment, for example /demo-shop
  4. 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.

<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.

window.pomelo?.track('boutique.contact_click', {
action_id: 'shop:contact_click',
targetTenantId: 'tenant_demo_shop',
targetTenantSlug: 'demo-shop',
targetTenantName: 'Demo Shop',
});
window.pomelo?.clearTenant();
Terminal window
curl -sS -G "https://api.pomeloanalytics.com/v1/tenants" \
-H "Authorization: Bearer $POMELO_API_TOKEN" \
--data-urlencode "site_id=site_marketplace"
Terminal window
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"
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"

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 can be restricted with:

  • allowedSiteIds
  • allowedTenantIds

When a token is restricted to tenants, always send tenant_id on analytics queries.