Show the prompt the moment a limit is hit, and name the limit
A trial admin has just invited a fourth teammate to a workspace whose plan allows three. The upgrade prompt runs on the trial calendar, so the next one is due on the last day of the trial, and the one before it went out on a day when nothing was blocked. The moment to ask is now, in the invite dialog, with the seat limit named, because seats are the limit this workspace has just run into.
last_limit_hit- The plan limit this workspace hit most recently
minutes_since_limit_hit- Minutes since a limit was last hit in this workspace
Shows the upgrade prompt in the dialog where the limit was hit, within minutes of the hit, and names that limit and the plan that lifts it. The plan table comes from your billing system. Signals supplies which limit was hit and when.
from datetime import timedelta
from snowplow_signals import (
Attribute, AttributeKey, EntityProperty, Event, EventProperty, StreamAttributeGroup,
)
plan_limit_hit = Event(name="plan_limit_hit", vendor="com.example", version="1-0-0")
workspace = AttributeKey(
name="workspace",
property=EntityProperty(vendor="com.example", name="workspace", major_version=1, path="id"),
)
last_limit_hit = Attribute(
name="last_limit_hit",
type="string",
events=[plan_limit_hit],
aggregation="last",
property=EventProperty(vendor="com.example", name="plan_limit_hit", major_version=1, path="limit"),
ttl=timedelta(days=30),
)
minutes_since_limit_hit = Attribute(
name="minutes_since_limit_hit",
type="double",
events=[plan_limit_hit],
aggregation="time_since_last",
time_unit="min",
)
# Plan limits belong to the workspace, not the user, so the group keys on the workspace id.
saas_upgrade_limit = StreamAttributeGroup(
name="saas_upgrade_limit",
version=1,
attribute_key=workspace,
owner="you@example.com",
attributes=[last_limit_hit, minutes_since_limit_hit],
)// In the code that renders the workspace after a blocked action
const workspace = await signals.getServiceAttributes({
name: "saas_upgrade_limit",
attribute_key: "workspace",
identifier: workspaceId,
});
// { last_limit_hit: "seats", minutes_since_limit_hit: 0.4 }
if (workspace.minutes_since_limit_hit < 5) {
upgradePrompt.show({
placement: "inline",
limit: workspace.last_limit_hit,
plan: plans.liftsLimit(workspace.last_limit_hit),
});
}