DocsRecipes

Recipes

Multi-product and cross-product adoption analytics

4 min readReviewed July 2026

Product-suite analytics explains how customers adopt several products, move between them, and receive value from the portfolio as a whole. It should not collapse unlike products into one “active” event.

Keep product catalog, account hierarchy, entitlements, subscriptions, and migrations authoritative in their application and billing systems. Use GraphJSON to analyze stable product facts at a shared customer grain.

Define product and customer identities#

Use durable identifiers:

{
  "event": "product_value_completed",
  "organization_id": "org_3",
  "account_id": "acct_7",
  "workspace_id": "ws_12",
  "user_id": "usr_42",
  "product_code": "analytics",
  "capability_code": "scheduled_report",
  "outcome": "report_delivered",
  "product_definition_version": 2
}

Do not infer product from collection name alone. A shared event can support several products, and one product can emit to several collections.

For every product define:

  • eligible customer entity
  • activation
  • meaningful activity
  • retained value
  • commercial entitlement
  • definition version

Separate access from adoption#

An account may:

  • be entitled to a product
  • have it provisioned
  • start onboarding
  • activate
  • use it meaningfully
  • retain usage

Emit entitlement transitions from their authority:

{
  "event": "product_entitlement_changed",
  "account_id": "acct_7",
  "product_code": "automation",
  "previous_status": "not_entitled",
  "status": "entitled",
  "source": "subscription",
  "effective_at": "2026-07-25T18:00:00Z",
  "catalog_version": "2026_07_1"
}

Do not count bundle entitlement as adoption.

Emit product-specific activation#

{
  "event": "account_product_activated",
  "account_id": "acct_7",
  "product_code": "automation",
  "activation_version": 3,
  "activation_id": "acct_7:automation:v3",
  "qualifying_outcome": "first_workflow_completed",
  "activated_at": "2026-07-28T20:00:00Z"
}

The same account can activate each product at different times. Preserve the first activation and later reactivation separately.

Portfolio activation may require a combination, but it should be derived from the product-level facts rather than replace them.

Choose an anchor product#

For cross-product journeys, define:

  • anchor product or first product
  • attached product
  • anchor event time
  • attachment window
  • eligible account population
  • commercial and product definitions

Examples:

Accounts active in Analytics that activate Automation within 90 days
Accounts purchasing API Usage after first receiving Report value
Accounts migrating from Legacy Reports to Analytics

Do not call two products “cross-sold” when they were included in the same bundle from the beginning.

Calculate product attach#

WITH activations AS (
  SELECT
    JSONExtractString(json, 'account_id') AS account_id,
    JSONExtractString(json, 'product_code') AS product_code,
    min(toDateTime(timestamp)) AS activated_at
  FROM portfolio_events
  WHERE JSONExtractString(json, 'event') = 'account_product_activated'
  GROUP BY account_id, product_code
),
anchor AS (
  SELECT account_id, activated_at AS anchor_at
  FROM activations
  WHERE product_code = 'analytics'
),
attached AS (
  SELECT account_id, activated_at AS attached_at
  FROM activations
  WHERE product_code = 'automation'
)
SELECT
  toStartOfMonth(anchor.anchor_at) AS anchor_month,
  count() AS mature_anchor_accounts,
  countIf(
    attached.attached_at >= anchor.anchor_at
    AND attached.attached_at < anchor.anchor_at + INTERVAL 90 DAY
  ) AS attached_accounts,
  attached_accounts / nullIf(mature_anchor_accounts, 0) AS attach_rate
FROM anchor
LEFT JOIN attached USING account_id
WHERE anchor.anchor_at < now() - INTERVAL 90 DAY
GROUP BY anchor_month
ORDER BY anchor_month

Include only accounts eligible for the attached product. A regional, contractual, or technical exclusion should not appear as non-adoption.

Analyze adoption sequences#

Useful paths:

Analytics → Automation
API → Analytics → Scheduled Reports
Legacy Reports → Analytics
Commerce → Messaging

Collapse repeated activity into first meaningful activation per product before building paths. Otherwise heavy product use dominates the sequence.

Use Journey and path analysis for ordered SQL patterns.

Measure portfolio breadth and depth#

At the account grain:

  • entitled products
  • activated products
  • products active in the last 28 days
  • meaningful outcomes by product
  • members active in one versus several products
  • product concentration

Show a distribution of active-product count. An average of 1.8 products can hide a portfolio split between single-product and deeply adopted accounts.

Keep product-specific depth metrics. Ten API calls and ten completed workflows are not one comparable unit.

Model migrations explicitly#

{
  "event": "account_product_migration_completed",
  "migration_id": "mig_91",
  "account_id": "acct_7",
  "from_product_code": "legacy_reports",
  "to_product_code": "analytics",
  "migration_wave": "2026_q3_2",
  "result": "success",
  "started_at": "2026-07-20T18:00:00Z",
  "completed_at": "2026-07-25T18:00:00Z",
  "validation_version": 2
}

Migration is not ordinary attach. Preserve eligibility, start, completion, validation, rollback, and old-product retirement.

Measure retained customer outcomes after migration, not only technical completion.

Evaluate cannibalization and substitution#

After a new product launches, old-product use may fall because:

  • customers migrated successfully
  • the new product replaced the old workflow
  • tracking moved
  • old functionality degraded
  • customer mix changed

Compare compatible cohorts and total customer outcomes. Declining old-product usage is not automatically harmful if portfolio value and retention improve.

Use deployment and entitlement timing, and do not claim causality from a simple before-and-after chart.

Connect adoption to expansion#

Preserve product activation before the commercial outcome:

product activation window
  → expansion request or effective subscription change
  → retained value and contribution guardrails

Accounts that buy more products may already be larger and healthier. Control for account size, tenure, plan, sales motion, and prior engagement.

Use Behavioral driver analysis and Pricing and packaging analytics.

Protect tenant boundaries#

Cross-product identity joins can expand data access. Ensure:

  • the shared account mapping is authoritative
  • merged and split accounts preserve history
  • customer-facing reports authorize every product
  • caches include account and product scope
  • products with different sensitivity remain in appropriate collections

Entitlement to one product does not grant permission to view another product’s analytics.

Build the portfolio dashboard#

Show:

  1. eligible, entitled, activated, and retained accounts by product
  2. mature attach rate from each anchor product
  3. common product-activation sequences
  4. portfolio breadth distribution
  5. cross-product member participation
  6. migration progress and retained outcomes
  7. old-versus-new product substitution
  8. expansion and retention by prior adoption breadth
  9. catalog, activation, and identity versions
  10. source freshness

Avoid one blended “suite engagement” score without its product-level components.

Launch checklist#

  • Product, account, workspace, user, and entitlement identities are explicit.
  • Every product has its own activation and meaningful-activity contract.
  • Entitlement, provisioning, activation, and retention remain distinct.
  • Attach populations are eligible and mature.
  • Product paths use first meaningful activation, not repeated events.
  • Migrations remain separate from organic cross-product adoption.
  • Cannibalization analysis includes total customer outcomes.
  • Expansion comparisons control for prior account differences.
  • Cross-product authorization is tested per tenant and product.
  • Portfolio metrics retain product-level definitions.
Need a hand?

Tell us what you’re building and we’ll point you in the right direction.

Contact support