Skip to content

Create iOS Subscription Group

Subscription groups are essential for organizing and managing multiple subscription levels in your iOS app. Understanding how they work is crucial for implementing upgrade, downgrade, and crossgrade functionality.

What is a Subscription Group?

A subscription group is a collection of related subscriptions that users can choose between. Users can only subscribe to one subscription within a group at a time. When they switch subscriptions, Apple handles the transition automatically.

Why Subscription Groups Matter

Subscription groups enable:

  • Tiered pricing: Offer basic, premium, and ultimate plans
  • Different durations: Monthly, yearly, and lifetime options
  • Upgrade/downgrade logic: Automatic handling of subscription changes
  • Simplified management: Group related subscriptions together

Subscription Levels

Within a group, each subscription should be ranked from highest value (level 1) to lowest value. This ranking determines how subscription changes are classified:

Subscription group hierarchy

Level Examples

Level 1 (Highest Value)

  • Premium Annual ($99.99/year)
  • Ultimate Monthly ($19.99/month)

Level 2 (Medium Value)

  • Standard Annual ($49.99/year)
  • Premium Monthly ($9.99/month)

Level 3 (Lowest Value)

  • Basic Annual ($29.99/year)
  • Standard Monthly ($4.99/month)

Subscription Change Types

Apple automatically handles three types of subscription changes based on the level ranking:

1. Upgrade

Moving to a higher-tier subscription (e.g., level 2 → level 1).

Behavior:

  • Takes effect immediately
  • User receives prorated refund for remaining time
  • New subscription starts right away

Example:

// User currently has: Standard Monthly (Level 2)
// User upgrades to: Premium Annual (Level 1)
// Result: Immediate access to Premium, refund for unused Standard time

2. Downgrade

Moving to a lower-tier subscription (e.g., level 1 → level 2).

Behavior:

  • Takes effect at next renewal date
  • User keeps current subscription until period ends
  • New subscription starts automatically after expiration

Example:

// User currently has: Premium Annual (Level 1)
// User downgrades to: Standard Monthly (Level 2)
// Result: Premium access continues until annual renewal date, then switches

3. Crossgrade

Switching to another subscription at the same tier level.

Behavior depends on duration:

Different Duration → Behaves like downgrade

  • Takes effect at next renewal date
  • Example: Monthly Premium (Level 1) → Annual Premium (Level 1)

Same Duration → Behaves like upgrade

  • Takes effect immediately
  • Example: Premium Monthly (Level 1) → Ultimate Monthly (Level 1)

Creating a Subscription Group

  1. Navigate to Subscriptions

    In App Store Connect, select your app and go to Monetize > Subscriptions.

  2. Create Group

    Click + next to “Subscription Groups” to create a new group.

  3. Name the Group

    Choose a descriptive name that reflects the subscriptions it contains:

    • “Premium Access”
    • “Cloud Storage Plans”
    • “Pro Features”
  4. Add Subscriptions

    After creating the group, add individual subscriptions to it. Each subscription will have a level ranking.

  5. Set Level Rankings

    Arrange subscriptions from highest value (1) to lowest value. Consider:

    • Annual plans typically rank higher than monthly
    • Higher-priced tiers rank above lower-priced ones
    • Ultimate/premium tiers rank highest

Using in Your App

The native-purchases plugin automatically handles subscription group logic:

import { NativePurchases } from '@capgo/native-purchases';
// Fetch all subscriptions in a group
const { products } = await NativePurchases.getProducts({
productIdentifiers: [
'premium_monthly',
'premium_annual',
'ultimate_monthly'
]
});
// Display current subscription
const { customerInfo } = await NativePurchases.getCustomerInfo();
const activeSubs = customerInfo.activeSubscriptions;
// Check for pending downgrade
if (customerInfo.subscriptionRenewalProduct) {
console.log('Subscription will change to:',
customerInfo.subscriptionRenewalProduct);
}
// Purchase (automatically handles upgrade/downgrade)
await NativePurchases.purchaseProduct({
productIdentifier: 'premium_annual'
});
// Listen for subscription changes
NativePurchases.addListener('customerInfoUpdate', (info) => {
console.log('Subscription updated:', info.customerInfo);
});

Handling Subscription Changes

Detecting Change Type

// Get current subscription info
const { customerInfo } = await NativePurchases.getCustomerInfo();
// Check if downgrade is pending
if (customerInfo.subscriptionRenewalProduct) {
// User has downgraded, will change at next renewal
const currentProduct = customerInfo.activeSubscriptions[0];
const futureProduct = customerInfo.subscriptionRenewalProduct;
console.log(`Currently: ${currentProduct}`);
console.log(`Changes to: ${futureProduct} at next renewal`);
}
// Check for immediate upgrade
NativePurchases.addListener('customerInfoUpdate', (info) => {
// This fires immediately for upgrades
console.log('Subscription changed!');
});

User Communication

Always communicate the change behavior clearly:

For Upgrades:

“You’ll get immediate access to Premium features. We’ll prorate your current subscription.”

For Downgrades:

“You’ll keep Premium access until [renewal date], then switch to Standard.”

For Crossgrades:

“Your plan will change to Annual billing at the next renewal on [date].”

Webhooks

The native-purchases plugin triggers webhooks for subscription changes:

// subscription_replace webhook fired when user changes subscriptions
{
"type": "subscription_replace",
"oldProduct": "premium_monthly",
"newProduct": "premium_annual",
"effectiveDate": "2024-01-15T00:00:00Z",
"isUpgrade": false // Crossgrade (monthly to annual)
}

Best Practices

Group Organization

  • Keep related subscriptions in the same group
  • Don’t mix unrelated features (e.g., storage and ad removal)
  • Create separate groups for different feature sets

Level Ranking Strategy

  • Annual plans → Higher level than monthly (for same tier)
  • Higher-priced tiers → Higher level
  • Consider value, not just price

User Experience

  • Show current subscription clearly
  • Display all available options in the group
  • Indicate which changes are immediate vs. at renewal
  • Allow easy switching between plans

Testing

  • Test all upgrade scenarios
  • Test all downgrade scenarios
  • Verify crossgrade behavior
  • Check webhook firing

Common Scenarios

Scenario 1: Three-Tier Monthly Plans

Level 1: Ultimate Monthly ($19.99)
Level 2: Premium Monthly ($9.99)
Level 3: Basic Monthly ($4.99)
  • Basic → Premium: Upgrade (immediate)
  • Premium → Ultimate: Upgrade (immediate)
  • Ultimate → Premium: Downgrade (at renewal)
  • Basic → Ultimate: Upgrade (immediate)

Scenario 2: Mixed Duration Plans

Level 1: Premium Annual ($99.99/year)
Level 2: Premium Monthly ($9.99/month)
  • Monthly → Annual: Crossgrade (at renewal)
  • Annual → Monthly: Downgrade (at renewal)

Scenario 3: Multi-Tier Multi-Duration

Level 1: Ultimate Annual ($199/year)
Level 2: Ultimate Monthly ($19.99/month)
Level 3: Premium Annual ($99/year)
Level 4: Premium Monthly ($9.99/month)
Level 5: Basic Annual ($49/year)
Level 6: Basic Monthly ($4.99/month)

This setup provides maximum flexibility while maintaining clear upgrade/downgrade logic.

Troubleshooting

Subscription not appearing in group:

  • Verify it’s assigned to the correct group
  • Check that it’s in at least “Ready to Submit” status
  • Ensure product ID is correct

Wrong upgrade/downgrade behavior:

  • Review level rankings (1 = highest)
  • Verify subscription tiers make sense
  • Check that levels are set correctly

Products from different groups:

  • Users can subscribe to multiple groups simultaneously
  • This is intentional - keep related products in same group

getActiveProducts showing multiple subscriptions:

  • Check if subscriptions are in different groups
  • Verify user isn’t subscribed via Family Sharing
  • Review subscription status in App Store Connect

Additional Resources

For more details, refer to the official Apple documentation on subscription groups.