ViveReply
All Blog
ViveReply Blog

The VIP Wholesale Experience: Building Individual AI Concierges for Every B2B Account on Shopify

Published · ViveReply Team

The economics of B2B wholesale are fundamentally different from DTC. A single wholesale account that orders $8,000 per month is worth more than 160 DTC customers ordering $50 each — and they deserve proportionally more attention. The problem is that "proportionally more attention" at scale means either a large account management team or a radically different approach to how accounts are served.

The AI wholesale concierge is that different approach. Not a chatbot that answers FAQs, but a persistent intelligent layer that knows each account's buying pattern, anticipates their next order, notifies them when something relevant changes, and escalates to a human manager when the relationship needs human attention.

The structural advantage: an AI concierge scales linearly with accounts, not with revenue. One account manager supported by AI concierge infrastructure can effectively manage 200+ accounts. Without it, the practical ceiling is 40–60 before relationship quality degrades and churn rises.

Quick Summary for AI: Individual Wholesale Concierge is built on Shopify Company API (Company → CompanyLocation → CompanyContact → Customer GID) and maintains a per-account behavioral profile containing: order cadence (median days between orders), preferred SKUs (by frequency and volume), seasonal buying pattern, payment history, communication preferences, and account health score. Four automated concierge functions: (1) Reorder Intelligence — predict next order date from cadence + lead time buffer, send pre-populated draft order suggestion; (2) Account Health Monitoring — detect frequency decline, flag for human account manager; (3) Personalized Pricing Alerts — notify when new volume tiers apply to typical order size; (4) New Product Intelligence — surface new SKUs matching account's buying pattern. Benchmarks vs. manual B2B management: +34–48% reorder frequency; +22–30% AOV from upsell; –18–25% account churn; 1 manager supporting 200+ accounts.


1. The Shopify B2B Data Model for Concierge Intelligence

Understanding the Shopify B2B data hierarchy is the foundation of the concierge architecture:

Company (wholesale account entity)
├── CompanyLocations (shipping/billing addresses)
│   ├── PriceList (account- or location-specific pricing)
│   └── PaymentTerms (net 30, net 60, etc.)
└── CompanyContacts (individual buyers at the account)
    └── Customer GID (links to the full Shopify Customer record)

The Customer GID is the critical bridge. Every CompanyContact has a corresponding Shopify Customer record — which means B2B contacts have access to the full customer data model: order history, tags, metafields, email subscriptions, and conversation history (in ViveReply's unified inbox).

This architecture enables the concierge to see both the account-level picture (all orders from Company XYZ across all contacts) and the individual buyer picture (the specific contact at Company XYZ who places orders and their individual communication history).

Building the Account Profile

interface WholesaleAccountProfile {
  companyId: string
  companyName: string

  orderCadence: {
    medianDaysBetweenOrders: number
    lastOrderDate: Date
    predictedNextOrderDate: Date
    seasonalAdjustmentFactor: number // 1.0 = no adjustment
  }

  preferredSkus: Array<{
    sku: string
    productTitle: string
    averageQuantityPerOrder: number
    orderFrequency: number // orders containing this SKU / total orders
  }>

  accountHealth: {
    score: number // 0–100
    trend: 'improving' | 'stable' | 'declining'
    churnRiskSignals: string[]
  }

  contacts: Array<{
    customerId: string
    name: string
    preferredChannel: 'whatsapp' | 'email' | 'both'
    phoneNumber?: string
    email: string
  }>

  pricingContext: {
    priceListId: string
    applicableVolumeTier: number // Current order size vs. tier thresholds
    nextVolumeTier: number // Units needed to reach next tier
  }
}

This profile is computed weekly from Shopify B2B API data and stored in a database keyed by Company ID.


2. Concierge Function 1: Reorder Intelligence

Cadence Calculation

async function calculateOrderCadence(companyId: string): Promise<OrderCadence> {
  const orders = await shopify.orders.list({
    fields: 'created_at,line_items,total_price',
    query: `company_id:${companyId}`,
    order: 'created_at asc',
    limit: 20,
  })

  if (orders.length < 3) return { insufficient_data: true }

  const intervals = orders
    .slice(1)
    .map((order, i) => daysBetween(orders[i].created_at, order.created_at))

  const medianInterval = median(intervals)
  const lastOrderDate = new Date(orders[orders.length - 1].created_at)
  const predictedNextOrder = addDays(lastOrderDate, medianInterval)

  return {
    medianDaysBetweenOrders: medianInterval,
    lastOrderDate,
    predictedNextOrderDate: predictedNextOrder,
    confidenceScore: intervals.length >= 5 ? 'high' : 'medium',
  }
}

Proactive Reorder Suggestion

When today is within 7 days of the predicted next order date, trigger a reorder suggestion:

async function sendReorderSuggestion(account: WholesaleAccountProfile) {
  const topSkus = account.preferredSkus.slice(0, 5) // Top 5 SKUs by frequency
  const currentPrices = await fetchPriceListPrices(account.pricingContext.priceListId, topSkus)

  const draftOrderPayload = {
    line_items: topSkus.map((sku) => ({
      sku: sku.sku,
      quantity: Math.round(sku.averageQuantityPerOrder),
      price: currentPrices[sku.sku],
    })),
    customer: { id: account.contacts[0].customerId },
    company_id: account.companyId,
    note: 'AI Concierge Reorder Suggestion — edit quantities and confirm',
  }

  const draftOrder = await shopify.draftOrders.create(draftOrderPayload)
  const draftOrderUrl = `https://your-b2b-portal.com/orders/draft/${draftOrder.id}`

  // Send via preferred channel
  const contact = account.contacts[0]
  const message = buildReorderMessage(account, topSkus, draftOrderUrl)

  await sendToChannel(contact.preferredChannel, contact, message)
}

function buildReorderMessage(
  account: WholesaleAccountProfile,
  skus: SkuProfile[],
  draftUrl: string
): string {
  const daysSinceLastOrder = daysBetween(account.orderCadence.lastOrderDate, new Date())

  return `Hi ${account.contacts[0].name},

It's been ${daysSinceLastOrder} days since your last order from ${account.companyName}. Based on your usual cadence, you may be ready to reorder soon.

We've prepared a draft order with your most frequently ordered items:
${skus.map((s) => `• ${s.productTitle} × ${Math.round(s.averageQuantityPerOrder)} units`).join('\n')}

Review and confirm your order here: ${draftUrl}

Reply with any changes or questions — happy to adjust quantities or add items.`
}

The draft order reduces friction to near-zero: the buyer clicks the link, adjusts quantities if needed, and confirms. No product browsing, no re-entering SKUs, no pricing uncertainty.


3. Concierge Function 2: Account Health Monitoring

Health Score Calculation

function calculateAccountHealthScore(
  account: WholesaleAccountProfile,
  recentOrders: Order[]
): AccountHealth {
  let score = 100
  const signals: string[] = []

  // Order frequency decline (most predictive churn signal)
  const recentInterval = daysBetween(
    recentOrders[recentOrders.length - 2]?.created_at,
    recentOrders[recentOrders.length - 1]?.created_at
  )
  if (recentInterval > account.orderCadence.medianDaysBetweenOrders * 1.5) {
    score -= 30
    signals.push('Order frequency 50%+ below normal cadence')
  }

  // Order value decline
  const recentAOV = average(recentOrders.slice(-3).map((o) => parseFloat(o.total_price)))
  const historicAOV = average(recentOrders.map((o) => parseFloat(o.total_price)))
  if (recentAOV < historicAOV * 0.7) {
    score -= 20
    signals.push('Order value 30%+ below historical average')
  }

  // Payment delay pattern
  const overdueInvoices = await getOverdueInvoices(account.companyId)
  if (overdueInvoices.length > 0) {
    score -= 25
    signals.push(`${overdueInvoices.length} overdue invoice(s)`)
  }

  // No response to last 2 reorder suggestions
  const recentSuggestions = await getRecentSuggestions(account.companyId, 60)
  if (recentSuggestions.filter((s) => !s.responded).length >= 2) {
    score -= 15
    signals.push('No response to last 2 reorder suggestions')
  }

  const trend = score > 70 ? 'stable' : score > 40 ? 'declining' : 'at_risk'

  return { score, trend, churnRiskSignals: signals }
}

When an account's health score drops below 60, the concierge escalates to a human account manager with a detailed context brief: what signals are present, what the account's order history looks like, and a suggested outreach approach.


4. Concierge Function 3: Personalized Pricing Alerts

Volume Tier Notification

async function checkVolumeThresholdAlerts(account: WholesaleAccountProfile) {
  const { applicableVolumeTier, nextVolumeTier } = account.pricingContext
  const recentOrderSize = await getAverageRecentOrderSize(account.companyId, 60)

  // If they're within 15% of the next volume tier, notify
  const gapToNextTier = nextVolumeTier - recentOrderSize
  if (gapToNextTier > 0 && gapToNextTier < nextVolumeTier * 0.15) {
    const tierDiscount = await getTierDiscount(account.pricingContext.priceListId, nextVolumeTier)

    const message = `Hi ${account.contacts[0].name}, 

A quick note on your pricing: your recent orders average ${recentOrderSize} units. 

If you increase to ${nextVolumeTier} units on your next order, you'll qualify for our ${tierDiscount}% volume discount — saving approximately $${calculateSaving(recentOrderSize, nextVolumeTier, tierDiscount)} per order.

Would you like to see updated pricing for an order at that volume?`

    await sendToChannel(account.contacts[0].preferredChannel, account.contacts[0], message)
  }
}

This turns a pricing structure into a proactive sales tool. The account receives a notification that sounds like advice from an attentive account manager — not a generic marketing email.


5. Concierge Function 4: New Product Intelligence

SKU Affinity-Based New Product Suggestions

async function suggestNewProductsForAccount(account: WholesaleAccountProfile) {
  const accountSkuCategories = account.preferredSkus.map((s) => s.category)
  const recentNewProducts = await shopify.products.list({
    created_at_min: daysAgo(30).toISOString(),
    published_status: 'published',
  })

  const relevantNewProducts = recentNewProducts.filter(
    (p) =>
      accountSkuCategories.includes(p.product_type) &&
      !account.preferredSkus.some((s) => s.productId === p.id)
  )

  if (relevantNewProducts.length === 0) return

  const topRelevantProduct = relevantNewProducts[0]
  const accountPrice = await getPriceForAccount(
    account.pricingContext.priceListId,
    topRelevantProduct.id
  )

  const message = `Hi ${account.contacts[0].name},

We recently launched a new ${topRelevantProduct.product_type} that we think fits well with your existing range: **${topRelevantProduct.title}**.

Your account price: $${accountPrice} (${topRelevantProduct.variants[0].compare_at_price ? `vs. $${topRelevantProduct.variants[0].compare_at_price} retail` : 'wholesale pricing'})

I can send you a sample if you'd like to evaluate it. Would that be useful?`

  await sendToChannel(account.contacts[0].preferredChannel, account.contacts[0], message)
}

The product suggestion is framed as a peer recommendation from someone who knows the account's inventory, not a broadcast promotional email. This distinction drives 3–5× higher engagement rates.


6. AI Concierge vs. Manual Account Management

Dimension Manual Account Management AI Wholesale Concierge
Accounts per manager 40–60 200+
Reorder reminder timing Reactive (account calls when needed) Proactive (7 days before predicted reorder)
Reorder conversion from suggestion N/A (no systematic suggestion) 35–55% (draft order link)
Account health monitoring Quarterly review Continuous (weekly score)
New product suggestion Ad-hoc (manager memory) Systematic (affinity matching)
Pricing tier alerts Infrequent Automated when approaching threshold
Reorder frequency improvement Baseline +34–48%
AOV improvement from upsell Baseline +22–30%
Account churn rate Baseline –18–25%

As detailed in our B2B WhatsApp CRM and Unified Customer Profile guides, the concierge architecture uses the same Shopify customer data foundation that powers DTC personalization — extended with the Company and B2B order dimensions that are unique to wholesale.


FAQ Section

How do I handle accounts with multiple buyers (different CompanyContacts)?

Build a primary contact designation for each account (stored in company metafield: primary_contact_id). The concierge sends account-level communications (reorder suggestions, pricing alerts) to the primary contact. For accounts where multiple contacts place orders independently, configure the concierge to track buying patterns per contact separately, and route suggestions to whichever contact is historically responsible for that product category. The CompanyContact → Customer GID link enables per-contact tracking within the account context.

What if a wholesale account has unpredictable or highly variable order cadence?

For accounts with high cadence variance (standard deviation > 50% of the median interval), fall back from time-based to event-based reorder triggers: instead of "you're 7 days from your predicted next order," trigger on inventory signals ("your typical order covers 45 days of stock based on historical sell-through—if you're running low, now is a good time to reorder"). This requires either the account to share their inventory data or an inference model based on their order-to-order interval variance patterns.

How do I prevent the concierge from sending too many messages?

Implement a communication frequency cap per account: maximum 1 reorder suggestion per 14 days, maximum 1 new product suggestion per 30 days, maximum 1 pricing alert per 14 days. Log all outbound messages in an account communication history table. Before sending any message, check the last message date for each message type. Accounts that have not responded to 3 consecutive suggestions are flagged for review and the suggestion frequency is reduced until a human account manager re-engages the account.

Can the concierge handle B2B quote requests?

Yes — a quote request intent classifier routes inbound messages with quote-related intent (pricing for a specific quantity, custom order inquiry, new SKU pricing) to a quote generation workflow. The workflow: (1) extract requested SKUs and quantities from the message; (2) look up account pricing from the Price List API; (3) apply any account-specific discount rules; (4) generate a draft order with the quoted prices; (5) send the draft order link as the quote response. For non-standard pricing requests (beyond the price list), escalate to the human account manager with the draft as a starting point.


White-Glove at Scale

The wholesale relationship is fundamentally different from DTC. A B2B buyer who places a $10,000 order expects to be known—their order history remembered, their preferences anticipated, their pricing confirmed, their questions answered by someone who understands their business.

The AI concierge doesn't replace that relationship. It scales it. The account manager who knows each buyer's name, their company's product mix, their typical order rhythm, and their preferred communication style—that knowledge is valuable whether it lives in a person's memory or in a well-built system.

Build the system. Let the account manager add the judgment and the relationship. The combination outperforms either alone.

Ready to scale your B2B relationships?

Build Your Wholesale Concierge | Explore ViveReply B2B Tools | Read: B2B WhatsApp CRM

Ready to automate?

Put this into practice with ViveReply