الانتقال إلى المحتوى الرئيسي

المقدمة

Dub هي منصة قوية لإدارة الروابط تساعدك على إنشاء ومشاركة وتتبع الروابط القصيرة. من خلال دمج Dodo Payments مع Dub، يمكنك تتبع أحداث تحويل المبيعات تلقائيًا عندما يكمل العملاء عمليات الشراء، مما يتيح لك قياس العائد على الاستثمار لحملاتك التسويقية وبرامج الإحالة. يتم تسجيل حدث “بيع” في Dub عندما يقوم العميل:
  • بإكمال دفعة لمرة واحدة
  • بالاشتراك في خطة مدفوعة
  • بإجراء دفعة اشتراك متكررة
تتطلب هذه التكامل وجود حساب Dub مع تمكين تتبع التحويلات على الروابط الخاصة بك.

كيف يعمل

يتتبع Dub الزوار من خلال معرف نقرة فريد (dub_id) يتم تخزينه في ملف تعريف الارتباط عندما ينقر المستخدمون على روابط Dub القصيرة الخاصة بك. لت atribuir المبيعات إلى روابطك، تحتاج إلى:
  1. التقاط معرف نقرة Dub من ملف تعريف الارتباط dub_id عند إنشاء جلسات الدفع
  2. تخزين معرف النقرة في بيانات التعريف الخاصة بالدفع مع معرف العميل الخارجي
  3. إرسال بيانات البيع إلى Dub عندما تنجح المدفوعات باستخدام واجهة برمجة التطبيقات Track الخاصة بهم
هذا يسمح لـ Dub بمطابقة المبيعات الناجحة مع نقرة الرابط الأصلية، مما يمنحك نسبة تحويل كاملة.

المتطلبات الأساسية

قبل إعداد هذه التكامل، تأكد من أنك تمتلك:
  1. حساب Dub مع مساحة عمل
  2. تمكين تتبع التحويلات لروابطك
  3. مفتاح API الخاص بك من Dub (متاح في لوحة معلومات Dub الخاصة بك تحت الإعدادات → مفاتيح API)

البدء

1

تمكين تتبع التحويلات في Dub

في لوحة معلومات Dub الخاصة بك، قم بتمكين تتبع التحويلات للروابط التي تريد تتبع المبيعات لها. هذا يسمح لـ Dub بتسجيل أحداث البيع عندما يكمل العملاء عمليات الشراء.
تعرف على المزيد حول تمكين تتبع التحويلات في وثائق Dub.
2

احصل على مفتاح API الخاص بك من Dub

انتقل إلى لوحة معلومات Dub → الإعدادات → مفاتيح API وأنشئ مفتاح API جديد مع نطاق conversions.write.
احتفظ بمفتاح API الخاص بك آمنًا ولا تكشف عنه أبدًا في كود جانب العميل.
3

التقاط معرف النقرة في الدفع

عند إنشاء جلسة الدفع، قم بالتقاط معرف نقرة Dub من ملف تعريف الارتباط وأضفه إلى بيانات التعريف الخاصة بالدفع.
4

إرسال بيانات البيع عبر Webhook

قم بتكوين Webhook لإرسال بيانات البيع إلى واجهة برمجة التطبيقات Track الخاصة بـ Dub عندما تنجح المدفوعات.
5

تم!

ستظهر الآن أحداث تحويل البيع في لوحة معلومات تحليلات Dub الخاصة بك مع نسبة كاملة إلى روابطك.

دليل التنفيذ

الخطوة 1: إضافة معرف النقرة ومعرف العميل إلى بيانات التعريف الخاصة بالدفع

عند إنشاء جلسة الدفع، قم بالتقاط معرف نقرة Dub من ملف تعريف الارتباط وأدرجه في بيانات التعريف الخاصة بالدفع مع معرف العميل الخارجي الخاص بك.
import { cookies } from 'next/headers';
import DodoPayments from 'dodopayments';

const client = new DodoPayments();

export async function createCheckout(productId: string, customerId: string) {
  // Capture Dub click ID from cookie
  const dubClickId = cookies().get('dub_id')?.value;

  const payment = await client.payments.create({
    billing: {
      city: 'New York',
      country: 'US',
      state: 'NY',
      street: '123 Main St',
      zipcode: '10001',
    },
    customer: {
      email: '[email protected]',
      name: 'John Doe',
    },
    product_id: productId,
    metadata: {
      dub_click_id: dubClickId,           // Store Dub click ID
      dub_external_id: customerId,        // Store your customer's unique ID
    },
  });

  return payment;
}

الخطوة 2: إرسال بيانات البيع إلى Dub

قم بتكوين نقطة نهاية Webhook لإرسال بيانات البيع إلى واجهة برمجة التطبيقات Track الخاصة بـ Dub عندما تنجح المدفوعات.
1

فتح قسم Webhook

في لوحة معلومات Dodo Payments الخاصة بك، انتقل إلى Webhooks → + إضافة نقطة نهاية وقم بتوسيع قائمة التكاملات.
إضافة نقطة نهاية وقائمة التكاملات
2

اختيار Dub

اختر بطاقة تكامل Dub.
3

إدخال مفتاح API

قدم مفتاح API الخاص بك من Dub في حقل التكوين.
إضافة مفتاح API
4

تكوين التحويل

قم بتحرير كود التحويل لتنسيق بيانات الدفع لواجهة برمجة التطبيقات Track Sale الخاصة بـ Dub.
5

اختبار وإنشاء

اختبر باستخدام حمولات عينة وانقر على إنشاء لتفعيل التكامل.

أمثلة كود التحويل

تتبع المبيعات الأساسية

تتبع المبيعات عندما تنجح المدفوعات:
basic_sale.js
function handler(webhook) {
  if (webhook.eventType === "payment.succeeded") {
    const payment = webhook.payload.data;

    // Only send to Dub if click ID exists in metadata
    if (payment.metadata && payment.metadata.dub_click_id) {
      webhook.payload = {
        clickId: payment.metadata.dub_click_id,
        externalId: payment.metadata.dub_external_id || payment.customer.customer_id,
        amount: payment.total_amount, // Ensure the amount is in cents
        currency: payment.currency || "USD",
        paymentProcessor: "dodo",
        invoiceId: payment.payment_id,
        metadata: {
          customer_email: payment.customer.email,
          customer_name: payment.customer.name,
          product_id: payment.product_cart ? payment.product_cart.map(product => product.product_id).join(', ') : undefined,
        },
      };
    } else {
      // Cancel dispatch if no click ID (organic traffic)
      webhook.cancel = true;
    }
  }
  return webhook;
}

تتبع مبيعات الاشتراك

تتبع كل من الاشتراكات الأولية والمدفوعات المتكررة:
subscription_sale.js
function handler(webhook) {
  const data = webhook.payload.data;

  // Track initial subscription activation
  if (webhook.eventType === "subscription.active") {
    if (data.metadata && data.metadata.dub_click_id) {
      webhook.payload = {
        clickId: data.metadata.dub_click_id,
        externalId: data.metadata.dub_external_id || data.customer.customer_id,
        amount: data.recurring_pre_tax_amount, // Amount in cents
        currency: data.currency || "USD",
        paymentProcessor: "dodo",
        invoiceId: data.subscription_id,
        eventName: "Subscription Started",
        metadata: {
          subscription_id: data.subscription_id,
          product_id: data.product_id,
          billing_interval: data.payment_frequency_interval,
          customer_email: data.customer.email,
        },
      };
    } else {
      // Cancel dispatch if no click ID (organic traffic)
      webhook.cancel = true;
    }
  }

  // Track recurring subscription payments
  if (webhook.eventType === "subscription.renewed") {
    if (data.metadata && data.metadata.dub_click_id) {
      webhook.payload = {
        clickId: data.metadata.dub_click_id,
        externalId: data.metadata.dub_external_id || data.customer.customer_id,
        amount: data.recurring_pre_tax_amount,
        currency: data.currency || "USD",
        paymentProcessor: "dodo",
        invoiceId: `${data.subscription_id}_${Date.now()}`,
        eventName: "Subscription Renewed",
        metadata: {
          subscription_id: data.subscription_id,
          product_id: data.product_id,
          customer_email: data.customer.email,
        },
      };
    } else {
      // Cancel dispatch if no click ID (organic traffic)
      webhook.cancel = true;
    }
  }

  return webhook;
}

تتبع المبيعات مع استبعاد الضرائب

أرسل فقط المبلغ قبل الضريبة إلى Dub لتتبع الإيرادات بدقة:
sale_without_tax.js
function handler(webhook) {
  if (webhook.eventType === "payment.succeeded") {
    const payment = webhook.payload.data;

    if (payment.metadata && payment.metadata.dub_click_id) {
      // Calculate pre-tax amount (total minus tax)
      const preTaxAmount = payment.total_amount - (payment.tax || 0);

      webhook.payload = {
        clickId: payment.metadata.dub_click_id,
        externalId: payment.metadata.dub_external_id || payment.customer.customer_id,
        amount: preTaxAmount, // Pre-tax amount in cents
        currency: payment.currency || "USD",
        paymentProcessor: "dodo",
        invoiceId: payment.payment_id,
        metadata: {
          total_amount: payment.total_amount,
          tax_amount: payment.tax || 0,
          customer_email: payment.customer.email,
        },
      };
    } else {
      // Cancel dispatch if no click ID (organic traffic)
      webhook.cancel = true;
    }
  }
  return webhook;
}

تتبع المبيعات مع أسماء أحداث مخصصة

استخدم أسماء أحداث مخصصة لتصنيف أنواع مختلفة من المبيعات:
custom_events.js
function handler(webhook) {
  if (webhook.eventType === "payment.succeeded") {
    const payment = webhook.payload.data;

    if (payment.metadata && payment.metadata.dub_click_id) {
      // Determine event name based on payment type
      let eventName = "Purchase";
      if (payment.subscription_id) {
        eventName = "Subscription Purchase";
      } else if (payment.metadata && payment.metadata.is_upgrade) {
        eventName = "Plan Upgrade";
      }

      webhook.payload = {
        clickId: payment.metadata.dub_click_id,
        externalId: payment.metadata.dub_external_id || payment.customer.customer_id,
        amount: payment.total_amount,
        currency: payment.currency || "USD",
        paymentProcessor: "dodo",
        invoiceId: payment.payment_id,
        eventName: eventName,
        metadata: {
          product_id: payment.product_cart ? payment.product_cart.map(product => product.product_id).join(', ') : undefined,
          customer_email: payment.customer.email,
        },
      };
    } else {
      // Cancel dispatch if no click ID (organic traffic)
      webhook.cancel = true;
    }
  }
  return webhook;
}

بديل: تنفيذ جانب العميل

إذا كنت تفضل تتبع المبيعات من خادمك بدلاً من استخدام Webhooks، يمكنك استدعاء واجهة برمجة التطبيقات Track الخاصة بـ Dub مباشرة بعد نجاح الدفع:
'use server';

import { Dub } from 'dub';

const dub = new Dub();

export async function trackSale(
  paymentId: string,
  clickId: string,
  customerId: string,
  amount: number,
  currency: string
) {
  await dub.track.sale({
    clickId: clickId,
    externalId: customerId,
    amount: amount,
    currency: currency,
    paymentProcessor: 'dodo',
    invoiceId: paymentId,
  });
}

أفضل الممارسات

التقاط معرف النقرة مبكرًا: قم بتخزين معرف نقرة Dub في أقرب وقت ممكن في تدفق الدفع الخاص بك لضمان نسبة تحويل دقيقة، حتى لو انتقل المستخدم بعيدًا وعاد لاحقًا.
  • تأكد دائمًا من تضمين معرف النقرة في بيانات التعريف: بدون معرف النقرة، لا يمكن لـ Dub نسبة الإيرادات إلى روابطك
  • استخدم معرفات خارجية بشكل متسق: مرر نفس معرف العميل الذي تستخدمه في نظامك لتحليلات دقيقة على مستوى العميل
  • تعامل مع حركة المرور العضوية بشكل جيد: قم بتعيين webhook.cancel = true عندما لا يكون هناك معرف نقرة لتجنب مكالمات API غير الضرورية
  • اختبر باستخدام مدفوعات عينة: تحقق من أن التكامل يعمل بشكل صحيح قبل الذهاب إلى الإنتاج
  • راقب لوحة معلومات Dub الخاصة بك: تحقق من أن المبيعات تظهر بشكل صحيح مع نسبة تحويل مناسبة

ملاحظات مهمة

  • تنسيق المبلغ: يتوقع Dub المبالغ بالسنتات (على سبيل المثال، 10.00 دولار = 1000)
  • العملة: استخدم رموز العملة ISO 4217 (USD، EUR، GBP، إلخ)
  • التجارب المجانية: لا يتم تتبع المدفوعات بقيمة 0.00 دولار كمبيعات
  • الاستردادات: ضع في اعتبارك تتبع الاستردادات بشكل منفصل إذا لزم الأمر لتقارير الإيرادات الدقيقة

استكشاف الأخطاء وإصلاحها

  • تحقق من أن مفتاح API الخاص بك من Dub صحيح وله نطاق conversions.write
  • تحقق من أن dub_click_id يتم التقاطه وتخزينه في بيانات التعريف الخاصة بالدفع
  • تأكد من أن تحويل Webhook يقوم بتنسيق الحمولة بشكل صحيح
  • تحقق من أن Webhook يتم تفعيله على أحداث payment.succeeded
  • تأكد من تمكين تتبع التحويلات لروابط Dub الخاصة بك
  • تأكد من أن المستخدمين ينقرون على روابط Dub القصيرة الخاصة بك قبل الدفع
  • تحقق من أن ملف تعريف الارتباط dub_id يتم تعيينه بشكل صحيح على نطاقك
  • تحقق من أن معرفات النقرة تتطابق بين إنشاء الدفع وإكمال الدفع
  • تأكد من أنك تلتقط معرف النقرة قبل إنشاء جلسة الدفع
  • تحقق من أن هيكل JSON يتطابق مع تنسيق واجهة برمجة التطبيقات Track Sale الخاصة بـ Dub
  • تحقق من أن جميع الحقول المطلوبة (clickId، externalId، amount) موجودة
  • تأكد من أن المبلغ بالسنتات (عدد صحيح، وليس عشري)
  • تحقق من أن عنوان URL لنقطة نهاية واجهة برمجة التطبيقات صحيح: https://api.dub.co/track/sale
  • اختبر التحويل باستخدام حمولات Webhook عينة
  • تأكد من أنك تتبع فقط على أحداث payment.succeeded، وليس payment.processing
  • استخدم قيم invoiceId الفريدة لكل عملية بيع
  • بالنسبة للاشتراكات، أضف الطوابع الزمنية أو فترة الفوترة لمنع التكرار عند التجديدات

موارد إضافية

هل تحتاج إلى مساعدة؟ اتصل بدعم Dodo Payments على [email protected] للحصول على المساعدة في التكامل.