Offer a pause or a smaller plan while the page is open
A user who was in the product most working days has logged in twice this month, and now they are on the cancel page. The save email is written for the moment after the cancellation, so it reaches an inbox after the user has decided and the seat has gone. The offer belongs on this page, next to the cancel button and never over it, while the user is still making up their mind. It lands better when it names the one thing they kept coming back for.
sessions_30d- Separate sessions in the last 30 days
cancel_page_views_1h- Times the cancel page was opened in the last hour
top_feature_30d- The feature they used most in the last 30 days
Shows a pause or a smaller plan beside the cancel button when a user's sessions have fallen off this month, names the feature they used most in the offer, and leaves the cancel button where it is.
from datetime import timedelta
from snowplow_signals import (
Attribute, AtomicProperty, Criteria, Criterion, Event, EventProperty, StreamAttributeGroup, user_id,
)
page_view = Event(name="page_view", vendor="com.snowplowanalytics.snowplow", version="1-0-0")
feature_used = Event(name="feature_used", vendor="com.example", version="1-0-0")
sessions_30d = Attribute(
name="sessions_30d",
type="int32",
events=[page_view],
aggregation="approx_count_distinct",
property=AtomicProperty(name="domain_sessionid"),
period=timedelta(days=30),
)
cancel_page_views_1h = Attribute(
name="cancel_page_views_1h",
type="int32",
events=[page_view],
aggregation="counter",
criteria=Criteria(all=[
Criterion.like(AtomicProperty(name="page_url"), "%/settings/billing/cancel%"),
]),
period=timedelta(hours=1),
default_value=0,
)
top_feature_30d = Attribute(
name="top_feature_30d",
type="string",
events=[feature_used],
aggregation="most_frequent",
property=EventProperty(vendor="com.example", name="feature_used", major_version=1, path="feature"),
period=timedelta(days=30),
)
# Users are logged in, so this group keys on the user id.
saas_cancel_quiet = StreamAttributeGroup(
name="saas_cancel_quiet",
version=1,
attribute_key=user_id,
owner="you@example.com",
attributes=[sessions_30d, cancel_page_views_1h, top_feature_30d],
)// In the code that renders the cancel page
const user = await signals.getServiceAttributes({
name: "saas_cancel_quiet",
attribute_key: "user_id",
identifier: userId,
});
// { sessions_30d: 2, cancel_page_views_1h: 1, top_feature_30d: "reports" }
if (user.cancel_page_views_1h > 0 && user.sessions_30d <= 3) {
saveFlow.offer({
kind: "pause_or_smaller_plan",
keeps: user.top_feature_30d,
beside: "cancel_button",
});
}