pieowlDocs
Groups

Groups

Track analytics at the account, company, or team level — not just individual users.

Groups let you associate users with a shared entity — like a company, workspace, or team — and analyze behavior at that level. Instead of asking "what did Jane do?", you can ask "what is Acme Inc doing?"

This is especially useful for B2B SaaS products where a single paying account has many users.

How Groups work

There are two separate concepts:

  1. The group entity — created/updated with upsertGroup(). Stores metadata about the group (name, plan, etc.).
  2. Group membership — set with setGroup() / setGroups(). Links a user profile to one or more groups, and automatically attaches those group IDs to every subsequent track() call.

The examples use pieowl, a Pieowl instance from @pieowl/web or @pieowl/sdk. With the script tag, call the same methods on window.pieowl, for example window.pieowl('setGroup', 'org_acme').

Creating or updating a group

Call upsertGroup() to create a group or update its properties. The group is identified by its id and type.

typescript
pieowl.upsertGroup({
  id: 'org_acme',        // Your group's unique ID
  type: 'company',       // Group type (company, workspace, team, etc.)
  name: 'Acme Inc',      // Display name
  properties: {
    plan: 'enterprise',
    seats: 25,
    industry: 'logistics',
  },
});

Group payload

FieldTypeRequiredDescription
idstringYesUnique identifier for the group
typestringYesCategory of group (e.g. "company", "workspace")
namestringYesHuman-readable display name
propertiesobjectNoCustom metadata about the group

Managing groups in the dashboard

The easiest way to create, edit, and delete groups is directly in the Pieowl dashboard. Open your site and go to the Groups section — from there you can manage group names, types, and properties without touching any code.

upsertGroup() is the right tool when your group properties are dynamic and driven by your own data — for example, syncing a customer's current plan, seat count, or MRR from your backend at login time.

A good rule of thumb: call upsertGroup() on login or when group properties change — not on every request or page view. If you find yourself calling it frequently with the same data, the dashboard is probably the better place to manage that group.

Assigning a user to a group

After identifying a user, call setGroup() to link them to a group. This also attaches the group ID to all future track() calls for the current session.

typescript
// After login
pieowl.identify({ profileId: 'user_123' });

// Link the user to their organization
pieowl.setGroup('org_acme');

For users that belong to multiple groups:

typescript
pieowl.setGroups(['org_acme', 'team_engineering']);

setGroup() and setGroups() persist group IDs on the SDK instance. All subsequent track() calls will automatically include these group IDs until clear() is called.

Full login flow example

setGroup() doesn't require the group to exist first. You can call it with just an ID — events will be tagged with that group ID, and you can create the group later in the dashboard or via upsertGroup().

typescript
// 1. Identify the user
pieowl.identify({
  profileId: 'user_123',
  firstName: 'Jane',
  email: 'jane@acme.com',
});

// 2. Assign the user to the group — the group doesn't need to exist yet
pieowl.setGroup('org_acme');

// 3. All subsequent events are now tagged with the group
pieowl.track('dashboard_viewed');  // → includes groups: ['org_acme']
pieowl.track('report_exported');   // → includes groups: ['org_acme']

If you want to sync dynamic group properties from your own data (plan, seats, MRR), add upsertGroup() to the flow:

typescript
pieowl.identify({ profileId: 'user_123', email: 'jane@acme.com' });

// Sync group metadata from your backend
pieowl.upsertGroup({
  id: 'org_acme',
  type: 'company',
  name: 'Acme Inc',
  properties: { plan: 'pro' },
});

pieowl.setGroup('org_acme');

Per-event group override

You can attach group IDs to a specific event without affecting the SDK's persistent group state:

typescript
pieowl.track('file_shared', {
  filename: 'q4-report.pdf',
  groups: ['org_acme', 'org_partner'], // Only applies to this event
});

Groups passed in track() are merged with any groups already set on the SDK instance.

Clearing groups on logout

clear() resets the profile, device, session, and all groups. Always call it on logout.

typescript
function handleLogout() {
  pieowl.clear();
  // redirect to login...
}

Common patterns

B2B SaaS — company accounts

typescript
// On login
pieowl.identify({ profileId: user.id, email: user.email });
pieowl.upsertGroup({
  id: user.organizationId,
  type: 'company',
  name: user.organizationName,
  properties: { plan: user.plan, mrr: user.mrr },
});
pieowl.setGroup(user.organizationId);

Multi-tenant — workspaces

typescript
// When user switches workspace
pieowl.upsertGroup({
  id: workspace.id,
  type: 'workspace',
  name: workspace.name,
});
pieowl.setGroup(workspace.id);

Teams within a company

typescript
// User belongs to a company and a specific team
pieowl.setGroups([user.organizationId, user.teamId]);

API reference

upsertGroup(payload)

Creates the group if it doesn't exist, or merges properties into the existing group.

typescript
pieowl.upsertGroup({
  id: string;       // Required
  type: string;     // Required
  name: string;     // Required
  properties?: Record<string, unknown>;
});

setGroup(groupId)

Adds a single group ID to the SDK's internal group list and sends an assign_group event to link the current profile to that group.

typescript
pieowl.setGroup('org_acme');

setGroups(groupIds)

Same as setGroup() but for multiple group IDs at once.

typescript
pieowl.setGroups(['org_acme', 'team_engineering']);

What to avoid

  • Calling upsertGroup() on every event or page view — call it on login or when group properties actually change. For static group management, use the dashboard instead.
  • Not calling setGroup() after identify() — without it, events won't be tagged with the group and you won't see group-level data in the dashboard.
  • Forgetting clear() on logout — groups persist on the SDK instance, so a new user logging in on the same session could inherit the previous user's groups.
  • Using upsertGroup() to link a user to a group — upsertGroup() manages the group entity only. Use setGroup() to link a user profile to it.