मुख्य सामग्री पर जाएं
Upsells और downsells आपको संयोजित भुगतान तरीके का उपयोग करके ग्राहकों को अतिरिक्त उत्पाद या योजना परिवर्तन प्रदान करने देता है। इससे एक-क्लिक खरीदारी संभव होती है जो भुगतान वसूली को छोड़ देती है, और रूपांतरण दरों में जबरदस्त सुधार होता है।

Post-Purchase Upsells

चेकआउट के तुरंत बाद पूरक उत्पाद एक-क्लिक खरीदारी के साथ पेश करें।

Subscription Upgrades

स्वचालित प्रोरैशन और तात्कालिक बिलिंग के साथ ग्राहकों को उच्चतर स्तर में स्थानांतरित करें।

Cross-Sells

मौजूदा ग्राहकों को संबंधित उत्पाद जोड़ें बिना भुगतान विवरण फिर से दर्ज किए।

अवलोकन

Upsells और downsells शक्तिशाली राजस्व अनुकूलन रणनीतियाँ हैं:
  • Upsells: उच्च-मूल्य उत्पाद या अपग्रेड (उदा., Basic के बजाय Pro योजना) पेश करें
  • Downsells: जब ग्राहक अस्वीकार या डाउनग्रेड करे तो कम कीमत वाला विकल्प पेश करें
  • Cross-sells: पूरक उत्पाद सुझाएँ (उदा., ऐड-ऑन, संबंधित आइटम)
Dodo Payments payment_method_id पैरामीटर के माध्यम से इन फ्लो को सक्षम करता है, जो आपको ग्राहक का भुगतान तरीका बिना कार्ड विवरण दोबारा दर्ज किए चार्ज करने देता है।

मुख्य लाभ

लाभप्रभाव
एक-क्लिक खरीदारीलौटते ग्राहकों के लिए भुगतान फॉर्म पूरी तरह छोड़ें
उच्च रूपांतरणनिर्णय के समय घर्षण कम करें
तात्कालिक प्रोसेसिंगconfirm: true के साथ चार्ज तुरंत संसाधित होते हैं
सतत UXग्राहक पूरे फ्लो के दौरान आपके ऐप में बने रहते हैं

यह कैसे काम करता है

पूर्वापेक्षाएँ

Upsells और downsells लागू करने से पहले सुनिश्चित करें कि आपके पास है:
1

Customer with Saved Payment Method

ग्राहकों ने कम से कम एक खरीद पूरी की होनी चाहिए। भुगतान तरीके स्वचालित रूप से सहेजे जाते हैं जब ग्राहक चेकआउट पूरी करते हैं।
2

Products Configured

Dodo Payments डैशबोर्ड में अपने upsell उत्पाद बनाएँ। ये एक बार के भुगतान, सदस्यता या ऐड-ऑन हो सकते हैं।
3

Webhook Endpoint

payment.succeeded, payment.failed, और subscription.plan_changed इवेंट्स को संभालने के लिए वेबहुक सेटअप करें।

ग्राहक भुगतान तरीके प्राप्त करना

Upsell पेश करने से पहले ग्राहक के सहेजे गए भुगतान तरीके प्राप्त करें:
import DodoPayments from 'dodopayments';

const client = new DodoPayments({
  bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  environment: 'live_mode',
});

async function getPaymentMethods(customerId: string) {
  const paymentMethods = await client.customers.listPaymentMethods(customerId);
  
  // Returns array of saved payment methods
  // Each has: payment_method_id, type, card (last4, brand, exp_month, exp_year)
  return paymentMethods;
}

// Example usage
const methods = await getPaymentMethods('cus_123');
console.log('Available payment methods:', methods);

// Use the first available method for upsell
const primaryMethod = methods[0]?.payment_method_id;
ग्राहक चेकआउट पूरी करते ही भुगतान तरीके स्वचालित रूप से सहेजे जाते हैं। आपको उन्हें स्पष्ट रूप से सहेजने की आवश्यकता नहीं है।

पोस्ट-खरीद एक-क्लिक Upsells

सफल खरीद के तुरंत बाद अतिरिक्त उत्पाद पेश करें। ग्राहक एक ही क्लिक में स्वीकार कर सकते हैं क्योंकि उनका भुगतान तरीका पहले से सहेजा गया है।

कार्यान्वयन

import DodoPayments from 'dodopayments';

const client = new DodoPayments({
  bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  environment: 'live_mode',
});

async function createOneClickUpsell(
  customerId: string,
  paymentMethodId: string,
  upsellProductId: string
) {
  // Create checkout session with saved payment method
  // confirm: true processes the payment immediately
  const session = await client.checkoutSessions.create({
    product_cart: [
      {
        product_id: upsellProductId,
        quantity: 1
      }
    ],
    customer: {
      customer_id: customerId
    },
    payment_method_id: paymentMethodId,
    confirm: true,  // Required when using payment_method_id
    return_url: 'https://yourapp.com/upsell-success',
    feature_flags: {
      redirect_immediately: true  // Skip success page
    },
    metadata: {
      upsell_source: 'post_purchase',
      original_order_id: 'order_123'
    }
  });

  return session;
}

// Example: Offer premium add-on after initial purchase
async function handlePostPurchaseUpsell(customerId: string) {
  // Get customer's payment methods
  const methods = await client.customers.listPaymentMethods(customerId);
  
  if (methods.length === 0) {
    console.log('No saved payment methods available');
    return null;
  }

  // Create the upsell with one-click checkout
  const upsell = await createOneClickUpsell(
    customerId,
    methods[0].payment_method_id,
    'prod_premium_addon'
  );

  console.log('Upsell processed:', upsell.session_id);
  return upsell;
}
जब payment_method_id का उपयोग किया जाता है, तो confirm: true सेट करना और एक मौजूदा customer_id प्रदान करना आवश्यक है। भुगतान तरीका उसी ग्राहक का होना चाहिए।

सदस्यता अपग्रेड्स

स्वचालित प्रोरैशन हैंडलिंग के साथ ग्राहकों को उच्च-स्तरीय सदस्यता योजनाओं में स्थानांतरित करें।

प्रतिबद्धता से पहले पूर्वावलोकन

हमेशा योजना परिवर्तनों का पूर्वावलोकन करें ताकि ग्राहकों को ठीक से पता चले कि उन्हें कितना चार्ज किया जाएगा:
async function previewUpgrade(
  subscriptionId: string,
  newProductId: string
) {
  const preview = await client.subscriptions.previewChangePlan(subscriptionId, {
    product_id: newProductId,
    quantity: 1,
    proration_billing_mode: 'difference_immediately'
  });

  return {
    immediateCharge: preview.immediate_charge?.summary,
    newPlan: preview.new_plan,
    effectiveDate: preview.effective_date
  };
}

// Show customer the charge before confirming
const preview = await previewUpgrade('sub_123', 'prod_pro_plan');
console.log(`Upgrade will charge: ${preview.immediateCharge}`);

अपग्रेड को निष्पादित करें

async function upgradeSubscription(
  subscriptionId: string,
  newProductId: string,
  prorationMode: 'prorated_immediately' | 'difference_immediately' | 'full_immediately' = 'difference_immediately'
) {
  const result = await client.subscriptions.changePlan(subscriptionId, {
    product_id: newProductId,
    quantity: 1,
    proration_billing_mode: prorationMode
  });

  return {
    status: result.status,
    subscriptionId: result.subscription_id,
    paymentId: result.payment_id,
    invoiceId: result.invoice_id
  };
}

// Upgrade from Basic ($30) to Pro ($80)
// With difference_immediately: charges $50 instantly
const upgrade = await upgradeSubscription('sub_123', 'prod_pro_plan');
console.log('Upgrade status:', upgrade.status);

प्रोरैशन मोड

अपग्रेड करते समय ग्राहकों को कैसे बिल किया जाएगा चुनें:
मोडव्यवहारसर्वश्रेष्ठ के लिए
difference_immediatelyकीमत अंतर तुरंत चार्ज करता है (3030→80 = $50)सीधे अपग्रेड
prorated_immediatelyबिलिंग चक्र में बचे समय के आधार पर चार्ज करता हैसमय-आधारित बिलिंग
full_immediatelyनई योजना की पूरी कीमत चार्ज करता है, बचे समय की परवाह नहींबिलिंग चक्र रीसेट
सरल अपग्रेड फ्लो के लिए difference_immediately का उपयोग करें। जब आप वर्तमान योजना पर बाकी बचे समय को ध्यान में रखना चाहते हैं तो prorated_immediately का उपयोग करें।

क्रॉस-सेल्स

मौजूदा ग्राहकों के लिए पूरक उत्पाद जोड़ें बिना उन्हें भुगतान विवरण फिर से दर्ज कराने के।

कार्यान्वयन

async function createCrossSell(
  customerId: string,
  paymentMethodId: string,
  productId: string,
  quantity: number = 1
) {
  // Create a one-time payment using saved payment method
  const payment = await client.payments.create({
    product_cart: [
      {
        product_id: productId,
        quantity: quantity
      }
    ],
    customer_id: customerId,
    payment_method_id: paymentMethodId,
    return_url: 'https://yourapp.com/purchase-complete',
    metadata: {
      purchase_type: 'cross_sell',
      source: 'product_recommendation'
    }
  });

  return payment;
}

// Example: Customer bought a course, offer related ebook
async function offerRelatedProduct(customerId: string, relatedProductId: string) {
  const methods = await client.customers.listPaymentMethods(customerId);
  
  if (methods.length === 0) {
    // Fall back to standard checkout
    return client.checkoutSessions.create({
      product_cart: [{ product_id: relatedProductId, quantity: 1 }],
      customer: { customer_id: customerId },
      return_url: 'https://yourapp.com/purchase-complete'
    });
  }

  // One-click purchase
  return createCrossSell(customerId, methods[0].payment_method_id, relatedProductId);
}

सदस्यता डाउनग्रेड्स

जब ग्राहक निचले स्तर की योजना पर जाना चाहें, तो स्वचालित क्रेडिट के साथ बदलाव को सहजता से संभालें।

डाउनग्रेड कैसे काम करते हैं

  1. ग्राहक डाउनग्रेड का अनुरोध करता है (Pro → Basic)
  2. सिस्टम वर्तमान योजना पर शेष मूल्य की गणना करता है
  3. भविष्य के नवीनीकरण के लिए सदस्यता में क्रेडिट जोड़ा जाता है
  4. ग्राहक तुरंत नई योजना पर चला जाता है
async function downgradeSubscription(
  subscriptionId: string,
  newProductId: string
) {
  // Preview the downgrade first
  const preview = await client.subscriptions.previewChangePlan(subscriptionId, {
    product_id: newProductId,
    quantity: 1,
    proration_billing_mode: 'difference_immediately'
  });

  console.log('Credit to be applied:', preview.credit_amount);

  // Execute the downgrade
  const result = await client.subscriptions.changePlan(subscriptionId, {
    product_id: newProductId,
    quantity: 1,
    proration_billing_mode: 'difference_immediately'
  });

  // Credits are automatically applied to future renewals
  return result;
}

// Downgrade from Pro ($80) to Basic ($30)
// $50 credit added to subscription, auto-applied on next renewal
const downgrade = await downgradeSubscription('sub_123', 'prod_basic_plan');
difference_immediately के साथ किए गए डाउनग्रेड से मिलने वाले क्रेडिट्स सदस्यता-स्कोप्ड होते हैं और स्वचालित रूप से भविष्य के नवीनीकरण में लागू होते हैं। ये Customer Credits से अलग होते हैं।

पूर्ण उदाहरण: पोस्ट-खरीद Upsell फ्लो

यहाँ एक सफल खरीद के बाद upsell पेश करने का पूर्ण कार्यान्वयन है:
import DodoPayments from 'dodopayments';
import express from 'express';

const client = new DodoPayments({
  bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  environment: 'live_mode',
});

const app = express();

// Store for tracking upsell eligibility (use your database in production)
const eligibleUpsells = new Map<string, { customerId: string; productId: string }>();

// Webhook handler for initial purchase success
app.post('/webhooks/dodo', express.raw({ type: 'application/json' }), async (req, res) => {
  const event = JSON.parse(req.body.toString());
  
  switch (event.type) {
    case 'payment.succeeded':
      // Check if customer is eligible for upsell
      const customerId = event.data.customer_id;
      const productId = event.data.product_id;
      
      // Define upsell rules (e.g., bought Basic, offer Pro)
      const upsellProduct = getUpsellProduct(productId);
      
      if (upsellProduct) {
        eligibleUpsells.set(customerId, {
          customerId,
          productId: upsellProduct
        });
      }
      break;
      
    case 'payment.failed':
      console.log('Payment failed:', event.data.payment_id);
      // Handle failed upsell payment
      break;
  }
  
  res.json({ received: true });
});

// API endpoint to check upsell eligibility
app.get('/api/upsell/:customerId', async (req, res) => {
  const { customerId } = req.params;
  const upsell = eligibleUpsells.get(customerId);
  
  if (!upsell) {
    return res.json({ eligible: false });
  }
  
  // Get payment methods
  const methods = await client.customers.listPaymentMethods(customerId);
  
  if (methods.length === 0) {
    return res.json({ eligible: false, reason: 'no_payment_method' });
  }
  
  // Get product details for display
  const product = await client.products.retrieve(upsell.productId);
  
  res.json({
    eligible: true,
    product: {
      id: product.product_id,
      name: product.name,
      price: product.price,
      currency: product.currency
    },
    paymentMethodId: methods[0].payment_method_id
  });
});

// API endpoint to accept upsell
app.post('/api/upsell/:customerId/accept', async (req, res) => {
  const { customerId } = req.params;
  const upsell = eligibleUpsells.get(customerId);
  
  if (!upsell) {
    return res.status(400).json({ error: 'No upsell available' });
  }
  
  try {
    const methods = await client.customers.listPaymentMethods(customerId);
    
    // Create one-click purchase
    const session = await client.checkoutSessions.create({
      product_cart: [{ product_id: upsell.productId, quantity: 1 }],
      customer: { customer_id: customerId },
      payment_method_id: methods[0].payment_method_id,
      confirm: true,
      return_url: `${process.env.APP_URL}/upsell-success`,
      feature_flags: { redirect_immediately: true },
      metadata: { upsell: 'true', source: 'post_purchase' }
    });
    
    // Clear the upsell offer
    eligibleUpsells.delete(customerId);
    
    res.json({ success: true, sessionId: session.session_id });
  } catch (error) {
    console.error('Upsell failed:', error);
    res.status(500).json({ error: 'Upsell processing failed' });
  }
});

// Helper function to determine upsell product
function getUpsellProduct(purchasedProductId: string): string | null {
  const upsellMap: Record<string, string> = {
    'prod_basic_plan': 'prod_pro_plan',
    'prod_starter_course': 'prod_complete_bundle',
    'prod_single_license': 'prod_team_license'
  };
  
  return upsellMap[purchasedProductId] || null;
}

app.listen(3000);

सर्वोत्तम प्रथाएँ

Upsell पेश करने का सबसे अच्छा समय सफल खरीद के तुरंत बाद होता है जब ग्राहक खरीदारी के मनोदशा में होते हैं। अन्य प्रभावी क्षण:
  • फीचर उपयोग की माइलस्टोन के बाद
  • योजना सीमाओं के पास जाते समय
  • ऑनबोर्डिंग पूरा होने पर
एक-क्लिक चार्ज करने का प्रयास करने से पहले भुगतान तरीके की पुष्टि करें:
  • क्या यह उत्पाद की मुद्रा के साथ संगत है
  • क्या इसकी अवधि समाप्त नहीं हुई है
  • क्या यह ग्राहक से ही जुड़ा है
API इन चीज़ों को मान्य करेगा, लेकिन सक्रिय रूप से जांचने से UX सुधरता है।
जब एक-क्लिक चार्ज असफल हों:
  1. मानक चेकआउट फ्लो पर वापस जाएँ
  2. ग्राहक को स्पष्ट संदेश दें
  3. भुगतान तरीका अपडेट करने का विकल्प दें
  4. विफल चार्ज को बार-बार पुनः प्रयास न करें
जब ग्राहक मूल्य समझते हैं तो upsells बेहतर रूपांतरण करते हैं:
  • वे क्या प्राप्त कर रहे हैं बनाम वर्तमान योजना दिखाएँ
  • कुल कीमत नहीं, मूल्य अंतर को हाइलाइट करें
  • सामाजिक प्रमाण उपयोग करें (उदा., “सबसे लोकप्रिय अपग्रेड”)
  • हमेशा अस्वीकृत करने का आसान तरीका प्रदान करें
  • अस्वीकृति के बाद एक ही upsell बार-बार न दिखाएँ
  • यह ट्रैक और विश्लेषण करें कि किस upsell से रूपांतरण होता है ताकि ऑफ़र अनुकूलित हों

मॉनिटर करने के लिए वेबहुक्स

Upsell और डाउनग्रेड फ्लो के लिए इन वेबहुक इवेंट्स को ट्रैक करें:
इवेंटट्रिगरक्रिया
payment.succeededUpsell/क्रॉस-सेल भुगतान पूरा हुआउत्पाद वितरित करें, पहुंच अपडेट करें
payment.failedएक-क्लिक चार्ज असफल रहात्रुटि दिखाएँ, पुनः प्रयास या फॉलबैक का विकल्प दें
subscription.plan_changedअपग्रेड/डाउनग्रेड पूरा हुआफीचर्स अपडेट करें, पुष्टि भेजें
subscription.activeयोजना परिवर्तन के बाद सदस्यता फिर सक्रिय हुईनए स्तर तक पहुंच दें

Webhook Integration Guide

वेबहुक एंडपॉइंट कैसे सेट करें और सत्यापित करें जानें।

संबंधित संसाधन