Customer lifecycle inspector for Loops, Stripe and PostHog

By General Input

Open one screen each morning to see a paying customer's billing, product activity and email history, then send the right next email without leaving it.

Integrations

  • Loops.so
  • Stripe
  • PostHog

Type

App

Categories

  • Operations
  • Marketing

Build me a customer lifecycle inspector that my customer success manager and lifecycle marketing manager open every morning to answer two questions about a specific paying customer: what is going on with them, and what email should they get next. Loops has no customer history view of its own, so this app is the missing 360 view that sits on top of it. It is a two pane layout: a roster of paying customers on the left, and a full detail pane for the selected customer on the right.

Important design constraint to build around: Loops has no operation that lists or pages through all contacts. The only way to read a contact is Find Contact by email or userId. So the roster must be built from Stripe, and Loops data is fetched one contact at a time for whoever is selected. Do not try to build a paginated Loops audience browser, it is not possible.

Left pane, the roster. Populate it with Stripe List Subscriptions filtered by status, defaulting to active and trialing, and expand or follow through to the customer so each row can show the customer name, email, plan or price nickname, subscription status and current period end. Show subscription status as a small colored badge, and let the user switch the status filter to include past_due, canceled and unpaid. Add a search box at the top that runs Stripe Search Customers so someone can jump straight to a customer by email or name instead of scrolling. Selecting a row loads the detail pane and the selected customer should be reflected in the URL so a manager can share a link to a specific customer.

Right pane, the 360 detail view for the selected customer, organized into clear sections. Their Loops contact record from Find Contact using the Stripe customer email, showing first and last name, user group, subscribed status, and all custom properties. Their mailing list memberships: the Loops contact record returns mailingLists as an object mapping mailing list IDs to booleans such as { "cm1234abcd": true }, so call List Mailing Lists and join on the IDs to render readable list names with a toggle next to each one. Their suppression status from Get Contact Suppression Status, shown as a prominent warning banner when the contact is suppressed, and include the remaining monthly removal quota that operation returns so the manager knows what they are spending. Their billing history from Stripe List Invoices and List Charges filtered to that customer, rendered as a combined dated timeline with amounts, invoice status and whether each charge succeeded or failed, so failed payments are obvious at a glance. Their product activity from PostHog Execute HogQL Query, running a HogQL query against the events table matched on the customer email or distinct_id to return last seen date plus a count of key events over the last 30 days, displayed as a short list of event names with counts and the date last seen.

The manager must be able to act from this pane without leaving the app. Toggling a mailing list calls Loops Update Contact with mailingLists set to the changed list ID mapped to true or false. Editing contact properties uses Update Contact as well, with the field picker populated from List Contact Properties so the manager picks from properties that actually exist rather than typing raw keys. A control to fire a lifecycle sequence calls Send Event with an event name the manager chooses or types, which is how a Loops email workflow gets triggered for that contact. When the contact is suppressed, the warning banner carries a button that calls Remove Contact From Suppression List to lift it, with a confirmation step since removals draw down a monthly quota. Every action should optimistically update the pane and then refetch the affected section so the manager sees the true server state.

Add a "Write a lifecycle brief" button in the detail pane that starts a background agent for the selected customer. The agent reads that customer's Stripe billing history via List Invoices and List Charges, their product activity via PostHog Execute HogQL Query, and their Loops contact record via Find Contact. It then reasons about what actually changed rather than restating the numbers: is spend growing or shrinking, have invoices started failing, has product usage dropped off compared with the earlier part of the window, is the contact engaging with email or drifting. From that it judges a lifecycle stage and a churn risk level, and recommends the specific next email to send with a one line reason why that email and not another. The brief is written back into the app so it appears in the detail pane for that customer with a timestamp, and previous briefs stay visible so the team can see how a customer's read has shifted over time. As its final step the agent calls Loops Update Contact to stamp lifecycleStage and churnRisk onto the contact as custom properties, so future Loops segments and audiences can filter on them.

A few Loops details to bake in. Update Contact is an upsert, so it creates a contact if none matches the email, which is fine here since every roster row is a real paying customer. Update Contact accepts arbitrary camelCase top level keys and treats them as custom properties, which is exactly how the agent writes lifecycleStage and churnRisk. A contact can only hold a single user group value, so prefer custom properties over user groups for anything the agent produces and never overwrite the existing user group. Email query parameters must be URI encoded when finding a contact or checking suppression. Handle the case where a Stripe customer has no matching Loops contact gracefully by showing an empty state with a button to create the contact via Update Contact rather than an error.

Related prompts

Explore more prompts
Let support send one-off Loops emails without an engineerBuild audience segments from product usage and push to LoopsMonth-end Stripe finance pack, stored and shared in SlackRank your Intercom queue by what each customer pays youCatch the trials quietly dying before the card gets chargedWork every open Stripe dispute from one chargeback war roomLook up any customer's support, billing and CRM in one pageInvestor update studio that builds your board deck monthlySell and invoice Ghost newsletter sponsor slots in one boardSupport console that pairs Gladly chats with orders and refunds