Leveraging events in Affinity

Affinity emits events to broadcast crucial information about customer behavior, and listens for directives that let your custom code trigger Affinity behaviors. Use events to track customer journeys, synchronize custom content, and build custom flows.

🗒️

Note

This article applies to both the original Affinity experience (Affinity 1.0) and the new Affinity experience (Affinity 2.0). Version availability is noted for each event. If you're migrating from 1.0 to 2.0, see the migration section at the end of this article.

📘

Platform:

Shopify Checkout Integration
Migrated Shopify Checkout Integration


Before you start

You must be on the Recharge Plus or Custom pricing plans to make advanced customizations to the Affinity customer portal.


Event types

Event typeWhen it occursUse it forAvailable on
ClickWhen a customer begins an actionMeasuring intent or replacing the default Affinity flowAffinity 1.0, Affinity 2.0
ActionAfter an action completes successfullyMeasuring completed outcomesAffinity 1.0, Affinity 2.0
NavigationWhen the customer moves to another Affinity pageJourney analytics or page-specific extension behaviorAffinity 2.0
Slot lifecycleWhen slot content is added to or removed from the DOMManaging the lifecycle of custom code linked to slot contentAffinity 1.0
DirectiveSent by your code when you want Affinity to perform a supported behaviorOpening common actions or refreshing Affinity after external data changesAffinity 2.0

Click and action events

Click and action events describe different points in the same journey. For example, Recharge::click::skip is emitted when the customer clicks Skip, while Recharge::action::skip is emitted only after the order has been skipped. Comparing the two can show where customers abandon a flow.

ActionTriggerClick eventCompletion eventAvailable on
SkipThe customer clicks Skip from an order or the subscription management page.Recharge::click::skipRecharge::action::skip1.0, 2.0
UnskipThe customer clicks Unskip from an order or subscription page.Recharge::click::unskipRecharge::action::unskip1.0, 2.0
Manage subscriptionThe customer clicks Manage subscription.Recharge::click::manageSubscription1.0, 2.0
Order nowThe customer clicks Send now on the next order page.Recharge::click::orderNowRecharge::action::orderNow1.0, 2.0
RescheduleThe customer clicks Reschedule from an order or the subscription management page.Recharge::click::rescheduleRecharge::action::reschedule1.0, 2.0
CancelThe customer clicks Cancel this subscription on the Overview page (Affinity 2.0) or the Subscription details page.Recharge::click::cancel1.0, 2.0
ReactivateThe customer clicks Reactivate on the subscription management page, or the Affinity overview page if the customer doesn't have active subscriptions.Recharge::click::reactivateRecharge::action::reactivate1.0, 2.0
Changes to an upcoming orderAny change affecting an upcoming order, such as a new product being added, a subscription being updated, or an order being rescheduled.Recharge::action::orderChanged1.0, 2.0
⚠️

Warning

Recharge::click::cancel is gradually replacing Recharge::extension::cancellation_flow. If your existing extension listens to Recharge::extension::cancellation_flow, it continues to work, but use Recharge::click::cancel for new implementations.

Track customer behavior

Listen for events with document.addEventListener. The following example records when a customer starts and successfully completes the Skip flow:

document.addEventListener('Recharge::click::skip', event => {
  analytics.track('Affinity skip started', event.detail?.payload);
});
document.addEventListener('Recharge::action::skip', event => {
  analytics.track('Affinity skip completed', event.detail?.payload);
});

Click events occur before Affinity continues with its default behavior. To intercept a click event and replace the standard flow with your own experience, see Personalize user journeys with custom flow extensions.


Navigation events

🗒️

Note

Navigation events can only be used in Affinity 2.0.

Listen for Recharge::location::change to detect when a customer moves to another page in Affinity. The event detail includes the new path, which you can use for journey analytics:

document.addEventListener('Recharge::location::change', event => {
  analytics.track('Affinity page viewed', {
    path: event.detail?.pathname,
  });
});

Slot lifecycle events

🗒️

Note

Slot lifecycle events are only available in Affinity 1.0.

Slot lifecycle events are triggered when slot content is added to or removed from the Document Object Model (DOM). Use them to manage the lifecycle of custom code linked to slot content.

EventEvent name
MountedRecharge::slot::mounted
UnmountedRecharge::slot::unmounted

Slot content in Affinity is dynamically loaded, meaning it is not present in the DOM during the initial page render but is added shortly afterward. When developing advanced content extensions, host initial placeholder elements in Slots, then wait for those elements to be present in the DOM before initializing your custom code:

<script type="text/html" data-recharge-slot="overview.header">
  <div id="placeholder-for-my-app"></div>
</script>
document.addEventListener("Recharge::slot::mounted", (event) => {
  if (event.detail.name === "header" && event.detail.pathname === "/overview") {
    // Initialize my app
  }
});

Directives

🗒️

Note

Directives can only be used in Affinity 2.0.

Directives work in the opposite direction from events: your code dispatches a supported event for Affinity to receive and act on. Use directives to open common actions or refresh portal data after external changes.

What you want Affinity to doDirectiveOptional details
Open RescheduleRecharge::order::openRescheduleModalOmit detail to reschedule the complete upcoming charge, or provide subscriptionId to reschedule one active subscription.
Open SkipRecharge::order::openSkipModalOmit detail to skip the complete upcoming charge, or provide subscriptionId to skip one active subscription.
Open Order nowRecharge::order::openOrderNowModalNone
UnskipRecharge::order::unskipNone
Open Add productRecharge::order::openAddProductModalproductId opens a product directly; collectionIds opens a filtered product list. When both are provided, productId takes priority.
Open DiscountRecharge::order::openDiscountModalNone
Refresh Affinity dataAffinity:refreshNone

Dispatch a directive as a CustomEvent on document. Unlike events emitted by Affinity, directive details are placed directly on event.detail rather than inside event.detail.payload.

To open Reschedule for the complete upcoming charge:

document.dispatchEvent(new CustomEvent('Recharge::order::openRescheduleModal'));

To open Reschedule for one specific subscription:

document.dispatchEvent(
  new CustomEvent('Recharge::order::openRescheduleModal', {
    detail: { subscriptionId: 12345 },
  })
);

If custom code changes data outside the standard Affinity flow, dispatch the refresh directive so the page requests the latest data:

document.dispatchEvent(new CustomEvent('Affinity:refresh'));
📘

Note:

Directives only work while the part of Affinity that handles them is available. Order directives are intended for the Next order experience, and the Add product directive requires the Add product carousel to be available. A targeted Reschedule or Skip directive is ignored when subscriptionId doesn't identify an eligible active subscription.


Migrating event code to Affinity 2.0

If you built event-driven customizations on Affinity 1.0, review the following before migrating:

  • Recharge::extension::cancellation_flow is deprecated. It continues to work, but update your listeners to Recharge::click::cancel.
  • Slot lifecycle events are not available in 2.0. If your extension initializes custom code on Recharge::slot::mounted, it needs a new initialization strategy in 2.0. [TODO: Confirm, and document the 2.0 replacement pattern for content extensions if one exists.]
  • Event detail structure. Events emitted by Affinity place data in event.detail.payload; directive details are placed directly on event.detail. [TODO: Confirm whether this differs between 1.0 and 2.0.]
  • Click event payloads include subscription IDs. All click events include the relevant subscription IDs under event.detail.payload.subscriptionIds.

All click and action events use the same names in both versions, so intent/completion analytics carry over without changes.