Littledata MonitorAI guide

Annual upgrade series (Intercom)

Goal: every Finance persona at a paying, Shopify-billed, monthly customer gets a plain-text email explaining why their company uses Littledata, why a peak-season surge makes now the time to switch, and what an annual contract saves - and switches by replying, after which we send an annual contract to pay by invoice. A separate one-off email, Email C, goes to the stores the series never reaches: a retired plan whose cheapest current plan billed monthly saves them money, with no annual offer to make.

Intercom has no API for Series, so the series is built in the Intercom UI. Everything it reads is written by this repo:

Written by What
syncIntercomAnnualOfferAttributes (daily, after syncCustomersCron) the annual_offer_* and monthly_offer_* company attributes below
pushCustomerLeadsToIntercomCron (daily) the Persona: Finance / Persona: Founder contact tags, on every such person the leads database knows at the customer, whether or not they log in to Littledata; and the Primary app user tag on the customer’s most recently seen login (services/contacts/primaryAppUser.ts)
ld-shopify phase, is_annual, pay_by, plan_name, monthly_orders, tier_limit, complete_connections
syncIntercomRoiAttributes (each value compute) roi_headline, roi_explanation - why the company uses Littledata, in its own numbers

Who qualifies (September 2026 census)

Shopify-billed, monthly, paying, external stores - priced against today’s list (Flex $0 + $0.35/order, Scale $199 for 1,500 + $0.15, Plus $990 for 10,000 + $0.03) at 20% off the base on annual billing:

Pool Stores Would save Saving/yr Median saving
Live plan (Scale 38, Plus 8, Flex over ~455 orders) 89 81 $140k $478
Retired plan (Standard_2025 168, Pro_2025 86, Standard 56, …) 432 255 $319k $910

A retired-plan store saves only when a live tier is cheaper at its volume - 177 of the 432 (most of Pro2025, all of Enterprise_Plus_2025) would pay _more on any live tier and carry no offer (every annual_offer_* key blank), so the series never reaches them. Flex stores below the Flex/Scale break-even (455 orders a month) get no offer for the same reason.

Company attributes (annual_offer_*)

All from buildAnnualOfferAttributes. Money is whole USD (Intercom renders a float as 159.2); annual_offer_overage_fee is the exception. Every key is blanked (null) when a store stops qualifying - Intercom merges updates - so “no offer” is annual_offer_plan being unknown, and that is the one key the audience should test for presence.

API name Meaning
annual_offer_plan The live tier quoted (Scale, Plus, occasionally Flex): the cheapest one at last month’s volume once its base is discounted - always Scale or Plus; Flex has no base price so is never quoted
annual_offer_plan_changes true when that tier is not the plan the store is on (every retired plan; Flex→Scale and Scale→Plus on live ones)
annual_offer_legacy_plan true when the current plan is not on the price list - the invoice has to name a live tier first, so this picks Email B
annual_offer_current_monthly_cost What the store paid for last month’s orders on its current plan, base + overage
annual_offer_monthly_equivalent The same orders on annual_offer_plan billed annually: base × 0.8 + overage at list
annual_offer_annual_price The invoice: annual_offer_plan base × 12 × 0.8. Overage is billed on top, at annual_offer_overage_fee
annual_offer_annual_total monthly_equivalent × 12: what the year comes to at current volume, plan plus overage. Quote this beside the invoice amount, or a heavy-overage store reads $1,910 and pays $8,700
annual_offer_saving_per_year (current_monthly_cost − monthly_equivalent) × 12. Can be 0 when only the peak case saves
annual_offer_included_orders_per_year annual_offer_included_orders × 12 - the year’s allowance on an annual contract, which is the peak-season argument: a surge draws on the allowance rather than being charged as overage that month
annual_offer_bill_moves_with_orders true when the current plan would charge more at 1.5× last month’s orders (PEAK_SEASON_MULTIPLIER). false on a fixed-price plan - most retired ones - which is the condition for hiding the peak paragraph. The multiplier decides nothing else: an offer needs a positive saving at today’s volume
annual_offer_*_text (current_monthly_cost, monthly_equivalent, annual_total, saving_per_year, included_orders_per_year) The same numbers as strings with thousands separators (18,000). Intercom prints an integer attribute as 18000, so the emails use these; the integer twins stay for segment rules
annual_offer_included_orders, annual_offer_overage_fee The quoted tier’s included orders and per-order rate above them

The customer document records whether either family is on the company (annualOfferOnIntercom, annualOfferSyncedAt) so a store is blanked once, not nightly.

Company attributes (monthly_offer_*)

From buildMonthlyOfferAttributes: the cheapest live tier at its monthly list price (no discount, Flex included), for the same stores the annual family quotes - paying, Shopify-billed, monthly. Set only when the switch saves at least $25 and 10% a month, the same rule (cheaperLivePlan in planCost.ts) that puts the “switch plan” line on the value banner, so the banner and the email agree. A store already on its cheapest live tier has the family blank. It does not depend on the annual offer: a quiet retired-plan store whose best plan is Flex has a monthly offer and no annual one.

API name Meaning
monthly_offer_plan The live tier quoted (Flex, Scale, Plus). Test this for presence
monthly_offer_legacy_plan true when the current plan is not on the price list: once they move, they cannot move back
monthly_offer_current_monthly_cost What the store paid for last month’s orders on its current plan - the same figure as annual_offer_current_monthly_cost
monthly_offer_monthly_cost The same orders on monthly_offer_plan at list: base + overage
monthly_offer_saving_per_month The difference. Always at least $25
monthly_offer_included_orders, monthly_offer_overage_fee The quoted tier’s included orders and its first per-order rate above them
monthly_offer_plan_terms_text The plan in words: $199 a month including 1,500 orders, then from $0.15 an order, or $0.35 an order, with no monthly fee
monthly_offer_*_text (current_monthly_cost, monthly_cost, saving_per_month, saving_per_year) Formatted twins, as for the annual family. saving_per_year_text is the monthly saving × 12

Related, written by ld-shopify: offer_annual_offer and offer_*_price - a 30% discount on the base price only, live plans only, no overage. The series should not read them; Shopify applies 20%.

Building the series

Subscription type. Create an opt-out type “Account offers” (Settings → Email → Subscriptions) and put both emails under it. Do not reuse “Monitor AI monthly summary”: someone who unsubscribes from the ROI email has not unsubscribed from their account manager.

Audience - a dynamic segment, so a store joins the day its numbers say it saves and leaves the day they stop. Type is Leads and Users: the lead push tags a finance person who already logs in to Littledata on their user contact, and a Leads-only audience never sees them. Entry rules (contact-level, checked continuously):

With every rule but the orders floor, 237 of the 240 offered companies qualified (September 2026: 160 retired-plan, 77 live). 104 of them also carry a monthly offer (October 2026, median $136 a month), but the series does not quote it: Email C goes only to stores outside the series.

Exit rules: company is_annual is true; or annual_offer_plan is unknown; or company monthly_orders is less than 1500 (so a small store already in the series gets no follow-up); or the contact replied to any email in the series (Intercom’s “replied” condition). Goal: is_annual is true.

Steps:

  1. Rule split on company annual_offer_legacy_plan: false → Email A, true → Email B.
  2. Wait 10 days. If no reply, send the follow-up (A2 / B2 - the same email, shortened to the number).
  3. Wait 14 days. Tag the contact Annual offer: no reply and exit, so the next wave can exclude them.

Sender: a named account manager, not “Littledata”. Replies land in the Inbox; the reply is the conversion - the account manager sends the annual contract, invoiced, and flips payBy in the admin.

Merge tags use `` with a fallback set in the composer for every numeric field. Wrap Email A’s peak paragraph in a conditional block: show when annual_offer_bill_moves_with_orders is true and annual_offer_saving_per_year is less than 1000 - where the saving is already large (a busy Flex store) the number makes the case on its own. Email B has no peak paragraph: the point there is that they save by switching.

Email A - live plan (annual_offer_legacy_plan = false)

Subject: 's Littledata cost, before peak season

Hi ,

 uses Littledata to send complete, first-party order data from Shopify to
. 

Last month that cost $ for
 orders, billed month to month through Shopify.

[show when annual_offer_bill_moves_with_orders is true and annual_offer_saving_per_year < 1000]
That bill moves with your orders, so if you're expecting a peak-season surge, now is a good time
to switch to annual: the included monthly orders become an allowance for the year -
 orders per year on
.
[end]

On an annual contract for , your current volume works
out at $ a month, which saves
 about $ over the year.

At your current volume the year comes to $,
invoiced once. Nothing changes in the app.

If you'd like to switch, reply to this email and we'll send over an annual contract for you to
review.


When annual_offer_plan_changes is true (a Flex store moving to Scale), the second-to-last paragraph already names the new tier; no separate wording is needed.

Email B - retired plan (annual_offer_legacy_plan = true)

Subject: 's Littledata plan: a cheaper way to stay on it

Hi ,

 uses Littledata to send complete, first-party order data from Shopify to
. 

You're on our  plan, which we no longer sell. It carries on as
it is, at $ a month billed through
Shopify, but it can't be moved to annual billing - an annual contract has to be on one of the
current plans.

The good news is that the current  plan, on an annual
contract, is cheaper for you: 
orders a year included, and $ a month at
your current volume. Over the year that saves  about
$.

At your current volume the year comes to $,
invoiced once. The app, your connections and your data don't change - only the plan name and the
bill.

If you'd like to switch, reply to this email and we'll send over an annual contract for you to
review.


Follow-ups A2 / B2 (day 10, no reply)

Subject: Re: + the original subject

Hi ,

Quick one - the annual contract for  would come to
$ a year at your current volume, against about
$ a year saved on the current
month-to-month bill. Happy to send it over if it's useful; just reply here.


Email C - cheaper plan, billed monthly (standalone, outside the series)

A standalone Outbound email (dynamic audience, send once, during office hours), not a series step: “Nudge to latest pricing, for those with no annual offer”, live since 2026-10-05. It reaches the ~50 Shopify-billed monthly stores on a retired plan that have a monthly offer and no annual one - quiet stores whose cheapest current plan is Flex. The merchant switches themselves, in the app’s Billing page, because a Shopify charge needs their approval. Sent from “Edward from Littledata” under the Announcements subscription type.

Audience (Leads and Users, dynamic): company monthly_offer_plan has any value, annual_offer_plan is unknown, monthly_offer_legacy_plan is true, phase is paying, is_annual is false; email does not contain @littledata.io; person tag Persona: Finance or Persona: Founder or Primary app user; not unsubscribed from emails or from Announcements; last contacted more than 2 days ago.

Subject: A cheaper Littledata plan for

Hi ,

Last month  paid $ for
 orders on a plan we no longer sell.

The same order volume on our current  plan would have cost
$ - about $ a month
less, or $ over a year.

It's still billed monthly through Shopify, and includes all the latest features.

To switch, log in to the Littledata app, go to Billing and choose the new plan.

Regards,
Edward

The company is named with Intercom’s Company name, not plan_name: that attribute holds the internal id (Standard_2025). A store doing one order a month is quoted “would have cost $0” (Flex at $0.35 an order, rounded to whole dollars) - 2 of the 53 in October 2026.

Checking it