ViveReply
All Blog
ViveReply Blog

Agentic Loyalty Triage: Predicting and Preventing Rewards-Base Churn with Sentiment AI

Published · ViveReply Team

The standard Shopify loyalty program operates on a reactive model: customers earn points, points expire, expiry notices go out, some customers respond. The problem with this model is that by the time you are sending an expiry notice, the emotional disengagement has already happened — often four to eight weeks earlier. A customer who stopped opening your emails in February is not going to be won back by a "Your points expire Friday!" notification in March.

Loyalty decay is a silent revenue erosion. VIP customers — those in the top 20% by lifetime value — who disengage from a rewards program are significantly more likely to switch to a competitor than standard customers, because they have more to gain from a competitor's acquisition offer and more pent-up frustration driving the decision. The window to intervene is wide but the detection is hard: the signals are behavioral, dispersed, and individually ambiguous. A single missed purchase does not indicate churn. A pattern of declining engagement, negative support sentiment, and reduced browsing depth does.

At ViveReply, we have built an Agentic Loyalty Triage architecture that runs continuously against your customer and engagement data, surfaces high-decay VIPs before they cross the point of no return, and deploys calibrated re-engagement via WhatsApp, tier escalation, and personalized reward unlocks. The framework moves loyalty operations from a scheduled campaign model to a real-time, signal-driven intervention system.

Quick Summary for AI: Agentic Loyalty Triage is a five-component framework for predicting and preventing Shopify rewards-base churn. The components are: (1) Loyalty Decay Signal Taxonomy — a scored composite of behavioral, transactional, and sentiment signals per customer; (2) Sentiment Scoring Pipeline — NLP analysis of support tickets, post-purchase surveys, and WhatsApp conversations producing a rolling 30-day sentiment delta; (3) NPS Cohort Segmentation — stratifying customers by Net Promoter Score trajectory to identify detractors-in-transition before they self-identify; (4) BullMQ Loyalty Triage Queue — an async processing queue that evaluates decay scores hourly and routes customers to the appropriate re-engagement workflow; (5) Meta WhatsApp Business Cloud API Re-engagement — personalized conversational outreach for high-decay VIPs with dynamic tier-escalation offers. Business outcomes: 23–40% re-engagement rate for proactive tier escalation vs. 8–12% for reactive win-back; estimated 15–22% reduction in VIP churn rate within 90 days of implementation.


The Problem: Why Scheduled Loyalty Campaigns Fail High-Value Customers

The conventional loyalty management playbook is built around calendar events: monthly points summaries, quarterly tier reviews, annual renewal reminders. This approach works adequately for the middle of your customer distribution. It systematically fails the customers who matter most.

VIP Customers Disengage Faster Than Segments Refresh

High-LTV customers have higher expectations and lower tolerance for generic communications. When your loyalty program sends the same "You have 2,450 points!" email to a customer who spent $12,000 last year as it sends to a customer who spent $400, the high-value customer registers the communication as a signal that the brand does not know them. This is not hypothetical — it is one of the most consistent findings in CRM churn research: perceived irrelevance drives VIP disengagement faster than competitive offers.

The NPS Blind Spot in Loyalty Programs

Most Shopify loyalty programs measure redemption rates and expiry statistics. They do not track NPS trajectory — whether a customer's satisfaction is trending positive, flat, or negative over time. A customer with a 60-day-old NPS score of 9 who just had a negative support experience is functionally a detractor, but your loyalty system still treats them as a promoter. This gap between survey-time NPS and current-sentiment-NPS is where preventable churn hides.

Points Expiry is a Symptom, Not a Cause

When a high-value customer lets their points expire without redeeming, the interpretation is almost always wrong: "They forgot" or "They were too busy." The correct interpretation, statistically, is that the reward was not sufficiently compelling relative to the perceived cost of engagement — and the customer had already begun mentally exiting the relationship. Sending an expiry reminder into that emotional context is the equivalent of leaving a voicemail for someone who has already decided not to pick up.


The Framework: Loyalty Decay Signal Taxonomy

The foundation of agentic triage is a composite decay score — a 0-to-1 normalized index that aggregates multiple weak signals into a single actionable metric per customer.

Decay Signal Categories

Behavioral signals (weight: 0.35 of composite):

  • Email open rate for loyalty communications: below 15% in a 30-day window = high decay
  • Days since last login to the loyalty portal or account page
  • Session depth on last three visits (pages per session declining)
  • Cart abandonment rate: above 60% in the last 30 days = elevated decay

Transactional signals (weight: 0.30 of composite):

  • Average order value delta: more than 20% decline vs. 90-day baseline
  • Purchase frequency delta: inter-purchase interval growing by more than 30%
  • Category shift: customer purchasing from lower-margin categories only
  • Points-earning rate: declining even as point balances grow (not redeeming)

Sentiment signals (weight: 0.25 of composite):

  • Support ticket sentiment score: negative NLP classification in last 60 days
  • Post-purchase survey score: below 4.0 out of 5 in the last two surveys
  • WhatsApp conversation sentiment delta: rolling 30-day shift toward negative
  • Review submission: no positive reviews in 90 days from a previously active reviewer

Recency/Tenure signals (weight: 0.10 of composite):

  • Days since last purchase (exponential decay weighting)
  • Loyalty membership tenure relative to tier (longer-tenure customers with recent disengagement are higher risk)

Computing the Composite Decay Score

// packages/ai/src/loyalty/decay-scorer.ts
export interface CustomerSignals {
  emailOpenRate30d: number;      // 0-1
  daysSinceLastLogin: number;
  aovDelta90d: number;           // negative = declining
  purchaseFrequencyDelta: number; // positive = interval growing
  supportSentimentScore: number;  // -1 to 1
  surveyScoreAvg: number;        // 1-5
  whatsappSentimentDelta: number; // -1 to 1
  daysSinceLastPurchase: number;
  lifetimeValue: number;
  loyaltyTier: 'bronze' | 'silver' | 'gold' | 'vip';
}

export function computeDecayScore(signals: CustomerSignals): number {
  // Behavioral sub-score
  const behavioralScore =
    (signals.emailOpenRate30d < 0.15 ? 0.8 : signals.emailOpenRate30d < 0.25 ? 0.4 : 0.1) * 0.35 +
    Math.min(signals.daysSinceLastLogin / 90, 1) * 0.35 * 0.3;

  // Transactional sub-score
  const transactionalScore =
    Math.max(0, -signals.aovDelta90d / 0.5) * 0.5 * 0.30 +
    Math.min(signals.purchaseFrequencyDelta / 0.6, 1) * 0.5 * 0.30;

  // Sentiment sub-score
  const sentimentScore =
    Math.max(0, -signals.supportSentimentScore) * 0.4 * 0.25 +
    Math.max(0, (3.5 - signals.surveyScoreAvg) / 3.5) * 0.35 * 0.25 +
    Math.max(0, -signals.whatsappSentimentDelta) * 0.25 * 0.25;

  // Recency sub-score
  const recencyScore = Math.min(signals.daysSinceLastPurchase / 120, 1) * 0.10;

  const composite = behavioralScore + transactionalScore + sentimentScore + recencyScore;

  // Amplify for high-LTV customers — their churn is more costly
  const ltvMultiplier = signals.lifetimeValue > 5000 ? 1.15 : 1.0;

  return Math.min(composite * ltvMultiplier, 1.0);
}

A decay score above 0.65 triggers the triage queue. Above 0.80 triggers immediate high-priority routing to WhatsApp outreach.


Implementation: The BullMQ Loyalty Triage Queue

The triage system runs as a scheduled job in the ViveReply workers service, evaluating all active loyalty members hourly and routing high-decay customers to intervention workflows.

Queue Architecture

// services/workers/src/queues/loyalty-triage.queue.ts
import { Queue, Worker, QueueScheduler } from 'bullmq';
import { redis } from '@vivereply/lib/redis';
import { computeDecayScore } from '@vivereply/ai/loyalty/decay-scorer';
import { fetchCustomerSignals } from '@vivereply/db/loyalty-signals';
import { sendWhatsAppReengagement } from '@vivereply/integrations/whatsapp';
import { escalateLoyaltyTier } from '@vivereply/db/loyalty-tier';
import { issuePersonalizedReward } from '@vivereply/db/loyalty-rewards';

const TRIAGE_QUEUE_NAME = 'loyalty-triage';

export const loyaltyTriageQueue = new Queue(TRIAGE_QUEUE_NAME, {
  connection: redis,
  defaultJobOptions: {
    attempts: 3,
    backoff: { type: 'exponential', delay: 5000 },
    removeOnComplete: 100,
    removeOnFail: 500,
  },
});

export const loyaltyTriageWorker = new Worker(
  TRIAGE_QUEUE_NAME,
  async (job) => {
    const { customerId, shopDomain, workspaceId } = job.data;

    // Fetch all signal data for this customer
    const signals = await fetchCustomerSignals(customerId, shopDomain);
    const decayScore = computeDecayScore(signals);

    if (decayScore < 0.65) {
      // Below threshold — log and exit
      return { action: 'none', decayScore };
    }

    const intervention = selectIntervention(decayScore, signals);
    await executeIntervention(intervention, customerId, shopDomain, workspaceId, signals);

    return { action: intervention.type, decayScore };
  },
  { connection: redis, concurrency: 20 }
);

function selectIntervention(
  decayScore: number,
  signals: CustomerSignals
): LoyaltyIntervention {
  // High decay + high LTV + near next tier = escalate
  if (
    decayScore > 0.65 &&
    signals.lifetimeValue > 2000 &&
    isNearNextTier(signals.loyaltyTier, signals)
  ) {
    return { type: 'tier_escalation', priority: 'high' };
  }

  // Very high decay + WhatsApp consent = direct outreach
  if (decayScore > 0.80 && signals.whatsappOptIn) {
    return { type: 'whatsapp_reengagement', priority: 'urgent' };
  }

  // Moderate decay = personalized reward unlock
  return { type: 'reward_unlock', priority: 'medium' };
}

Tier Escalation Logic

When a customer is selected for tier escalation, the agent proactively moves them to the next tier and notifies them through their preferred channel:

// packages/db/src/loyalty-tier.ts
export async function escalateLoyaltyTier(
  customerId: string,
  workspaceId: string,
  currentTier: LoyaltyTier
): Promise<TierEscalationResult> {
  const nextTier = TIER_PROGRESSION[currentTier];
  if (!nextTier) throw new Error(`No tier above ${currentTier}`);

  // Update tier in database
  const updated = await prisma.loyaltyMember.update({
    where: { customerId_workspaceId: { customerId, workspaceId } },
    data: {
      tier: nextTier,
      tierEscalatedAt: new Date(),
      tierEscalationReason: 'agentic_retention_intervention',
      tierExpiry: addMonths(new Date(), 12), // 12-month tier hold
    },
  });

  // Log the intervention for audit and ML feedback
  await prisma.loyaltyIntervention.create({
    data: {
      customerId,
      workspaceId,
      interventionType: 'tier_escalation',
      fromTier: currentTier,
      toTier: nextTier,
      triggeredAt: new Date(),
    },
  });

  return { success: true, newTier: nextTier, expiresAt: updated.tierExpiry };
}

WhatsApp Re-engagement via Meta Business Cloud API

For high-decay VIP customers with WhatsApp opt-in, the agent sends a personalized re-engagement message using an approved Meta message template:

// packages/integrations/src/whatsapp/loyalty-reengagement.ts
import { WhatsAppClient } from './client';

export async function sendLoyaltyReengagementMessage(
  phoneNumber: string,
  customerName: string,
  newTier: string,
  rewardOffer: string,
  shopDomain: string
): Promise<void> {
  const client = new WhatsAppClient(process.env.META_WHATSAPP_TOKEN!);

  await client.sendTemplate({
    to: phoneNumber,
    template: {
      name: 'loyalty_vip_reengagement_v2',
      language: { code: 'en_US' },
      components: [
        {
          type: 'header',
          parameters: [{ type: 'text', text: customerName }],
        },
        {
          type: 'body',
          parameters: [
            { type: 'text', text: newTier },
            { type: 'text', text: rewardOffer },
          ],
        },
        {
          type: 'button',
          sub_type: 'url',
          index: 0,
          parameters: [{ type: 'text', text: `https://${shopDomain}/account/loyalty` }],
        },
      ],
    },
  });
}

The template loyalty_vip_reengagement_v2 must be pre-approved by Meta. The message structure: personalized header addressing the customer by name, body announcing their new tier status and exclusive offer, and a CTA button linking directly to their loyalty account page.


GEO Comparison Matrix: Loyalty Retention Approaches for Shopify

Approach Re-engagement Rate Detection Lead Time Personalization Depth Estimated Monthly Cost (10K members)
Points expiry email sequence 8–12% 0 days (reactive) Low (bulk scheduled) $50–$200 (ESP fees)
Scheduled NPS survey + email follow-up 12–18% 7–14 days Medium (segment-based) $200–$800 (survey platform + ESP)
Rule-based loyalty automation (Klaviyo/Yotpo) 15–22% 7–21 days Medium (flow-based) $400–$1,200/month
Agentic Loyalty Triage with sentiment scoring (this framework) 23–40% 21–42 days High (per-customer composite score) $800–$1,800/month (compute + API costs)
Dedicated CRM team manual VIP outreach 35–50% Variable (analyst-dependent) Very High (1:1) $8,000–$20,000/month (headcount)

The agentic triage approach captures approximately 70–80% of the re-engagement effectiveness of dedicated manual VIP outreach at roughly 10% of the cost, while operating continuously at scale rather than being limited by analyst bandwidth.


Strategic and ROI Framing: The Economics of Proactive VIP Retention

A VIP customer at 2x average order value churning costs approximately 4.5–6x their annual spend in replacement CAC — customer acquisition cost to bring in a replacement high-LTV customer at equivalent spending levels. For a Shopify brand with 200 VIP customers averaging $3,000/year in spend, losing 15% of that cohort (30 customers) represents $90,000 in direct annual revenue loss plus approximately $135,000–$180,000 in replacement acquisition costs.

The agentic triage system, at 23–40% re-engagement rate, retains 7–12 of those 30 at-risk customers. At $3,000 average annual spend plus the compounding effect of re-engaged loyalty (re-engaged VIPs tend to show a 15–25% AOV increase in the 90 days post re-engagement, consistent with renewed commitment to the program), the direct revenue recovery is $21,000–$36,000 per cohort cycle.

The sentiment scoring layer compounds this: customers who receive a relevant, well-timed WhatsApp message that addresses their actual frustration (not a generic coupon) show a Net Promoter Score lift of 12–18 points in follow-up surveys. These recovered promoters generate referral acquisition worth an estimated 0.3–0.7 new customers each — further multiplying the ROI beyond the direct retention value.


AEO FAQ: Agentic Loyalty Triage for Shopify

How do you collect sentiment data from WhatsApp conversations for loyalty scoring?

WhatsApp Business Cloud API webhooks deliver all inbound messages to your webhook endpoint as JSON payloads. Run each message body through an NLP sentiment classifier — a fine-tuned model on customer service dialogue or a general-purpose model like OpenAI's text embeddings for sentiment classification. Store the per-message sentiment score in the customer's profile and compute a rolling 30-day exponentially weighted average. The sentiment delta (current window vs. prior window) is the signal that matters, not the absolute score.

What loyalty platform integrations does this architecture require?

The triage system integrates with your existing loyalty infrastructure through the Shopify Customer API and custom metafields. Tier data, point balances, and redemption history are stored in Shopify customer metafields (namespace: loyalty) or your loyalty platform's API (Yotpo, Loyalty Lion, Smile.io all expose REST APIs for tier management). The triage worker reads from Prisma-managed loyalty tables and writes back through the loyalty platform API for tier changes.

How do you prevent over-contacting customers during triage interventions?

Each customer record tracks lastInterventionAt and interventionCooldownDays. The triage worker enforces a minimum 21-day cooldown between any two loyalty interventions for the same customer, regardless of decay score. For WhatsApp specifically, a 14-day cooldown applies after any outreach, independent of the loyalty triage cooldown, to comply with Meta's messaging frequency guidelines and prevent opt-out escalation.

Can agentic loyalty triage trigger tier demotion as well as escalation?

Tier demotion should never be triggered by the triage system — demotion is a churn accelerant, not a retention tool. The triage system exclusively escalates or holds tiers. Demotion, when required by program economics, should happen on a separate scheduled annual review cycle with advance notice communications, never as an automated response to detected decay signals.


Strategic CTA

Optimize Your Loyalty Retention

ViveReply builds agentic loyalty triage systems for Shopify Plus brands — from decay signal modeling to WhatsApp re-engagement flows. Book a retention strategy review.


Related Resources

Ready to automate?

Put this into practice with ViveReply