refVenuerefVenue
Docs
Track Conversion API

Track Conversion API

API reference for manually tracking conversions via webhook

Track Conversion API

Manually track conversions (signups and purchases) via direct API calls.

Endpoint

POST https://tracking.refvenue.com/v1/track-conversion

Authentication

Authenticate using your publishable Publishable key in the request body:

{
  "publishable_key": "refv_live_..."
}

Get your Publishable key from: SettingsAPI Keys/Secrets

Request Body

Option 1: Track with Referral Code (Traditional)

{
  "program_id": "string (required)",
  "ref_code": "string (required)",
  "customer_email": "string (required)",
  "publishable_key": "string (required)",
  "conversion_type": "signup | purchase (required)",
  "revenue_amount": "number (optional, required for purchase)",
  "customer_ip": "string (optional)",
  "customer_user_agent": "string (optional)"
}

Option 2: Track with Coupon Code (New!)

{
  "program_id": "string (required)",
  "coupon_code": "string (required)",
  "customer_email": "string (optional)",
  "publishable_key": "string (required)",
  "conversion_type": "signup | purchase (required)",
  "revenue_amount": "number (required for purchase)",
  "customer_ip": "string (optional)",
  "customer_user_agent": "string (optional)"
}

Parameters

Required Parameters

ParameterTypeDescription
program_idstringYour program ID
publishable_keystringYour API publishable key
conversion_typestringEither "signup" or "purchase"

Attribution (one required):

  • ref_code - Affiliate's unique referral code
  • coupon_code - Coupon code used at checkout

Optional Parameters

ParameterTypeDescription
customer_emailstringCustomer's email (required with ref_code)
revenue_amountnumberPurchase amount after discount (required for purchases)
customer_ipstringCustomer's IP address (for fraud detection)
customer_user_agentstringCustomer's user agent (for fraud detection)

Examples

Track Signup

curl -X POST https://tracking.refvenue.com/v1/track-conversion \
  -H "Content-Type: application/json" \
  -d '{
    "program_id": "prog_abc123",
    "ref_code": "JOHN123",
    "customer_email": "customer@example.com",
    "publishable_key": "pk_live_...",
    "conversion_type": "signup"
  }'

Track Purchase (with Email)

curl -X POST https://tracking.refvenue.com/v1/track-conversion \
  -H "Content-Type: application/json" \
  -d '{
    "program_id": "prog_abc123",
    "ref_code": "JOHN123",
    "customer_email": "customer@example.com",
    "publishable_key": "pk_live_...",
    "conversion_type": "purchase",
    "revenue_amount": 99.99,
    "customer_ip": "203.0.113.42",
    "customer_user_agent": "Mozilla/5.0..."
  }'

Track Purchase (with Coupon)

curl -X POST https://tracking.refvenue.com/v1/track-conversion \
  -H "Content-Type": application/json" \
  -d '{
    "program_id": "prog_abc123",
    "coupon_code": "SAVE20",
    "publishable_key": "pk_live_...",
    "conversion_type": "purchase",
    "revenue_amount": 80.00
  }'

Note: When using coupon_code, customer_email is optional (placeholder will be generated).

Responses

Success (200 OK)

{
  "success": true,
  "conversion_id": "conv_xyz789",
  "commission": 9.99,
  "status": "pending",
  "message": "Conversion tracked successfully"
}

Flagged for Review (200 OK)

{
  "success": true,
  "conversion_id": "conv_xyz789",
  "commission": 9.99,
  "status": "pending_review",
  "message": "Conversion tracked but pending fraud review"
}

Error Responses

Invalid Publishable Key (401)

{
  "error": "Invalid Publishable key"
}

Missing Fields (400)

{
  "error": "Missing required fields",
  "message": "Need program_id, conversion_type, and either ref_code or coupon_code"
}

Invalid Email (400)

{
  "error": "Invalid email address",
  "message": "Email format validation failed"
}

Disposable Email (400)

{
  "error": "Disposable email not allowed",
  "message": "Please use a permanent email address"
}

Invalid Affiliate (404)

{
  "error": "Invalid or inactive affiliate code"
}

Invalid Coupon (404)

{
  "error": "Invalid coupon code or inactive affiliate"
}

Rate Limited (429)

{
  "error": "Conversion rate limit exceeded",
  "message": "Daily conversion limit exceeded",
  "retry_after": 3600
}

Duplicate Conversion (409)

{
  "error": "Duplicate conversion detected",
  "message": "This email has already been tracked for this program"
}

Conversion Status

Conversions can have the following statuses:

StatusDescription
pendingAwaiting merchant approval
pending_reviewFlagged for fraud review
approvedApproved by merchant
rejectedRejected by merchant
refundedCustomer refunded
chargebackPayment disputed

Fraud Detection

The API includes automatic fraud detection:

Email Validation

  • Format validation
  • Disposable email detection (tempmail.com, etc.)
  • Suspicious patterns (test123@, etc.)
  • Plus addressing abuse (user+1@, user+2@, etc.)

Rate Limiting

  • Max 2 conversions/hour per affiliate
  • Max 10 conversions/day per affiliate
  • Prevents automated abuse

Geographic Checks

  • Same location detection (affiliate and customer)
  • Impossible travel detection
  • IP quality checking

Timing Validation

  • Too fast: < 10 seconds (likely bot)
  • Too slow: > 30 days (cookie expired)
  • Suspicious: 10-60 seconds (flagged but accepted)

Best Practices

Timing

Call the API after successful conversion:

// ✅ Good
await processPayment();
await trackConversion();
 
// ❌ Bad
await trackConversion();
await processPayment();  // What if this fails?

Error Handling

Always handle errors gracefully:

try {
  const response = await fetch('/v1/track-conversion', {
    method: 'POST',
    body: JSON.stringify(data)
  });
 
  if (response.status === 429) {
    console.warn('Rate limit hit');
  } else if (!response.ok) {
    console.error('Tracking failed');
  }
} catch (error) {
  console.error('Network error:', error);
  // Don't block user flow on tracking errors
}

Revenue Amount

Always pass post-discount amount:

const originalPrice = 100;
const discount = 20;
const finalAmount = originalPrice - discount;  // 80
 
await trackConversion({
  revenue_amount: finalAmount,  // ✅ Correct
  // revenue_amount: originalPrice,  // ❌ Wrong
});

IP Address

Include customer IP for fraud detection:

// Express/Node.js
const clientIP = req.headers['x-forwarded-for']?.split(',')[0] ||
                 req.headers['x-real-ip'] ||
                 req.connection.remoteAddress;
 
await trackConversion({
  customer_ip: clientIP
});

User Agent

Include user agent for device tracking:

// Express/Node.js
const userAgent = req.headers['user-agent'];
 
await trackConversion({
  customer_user_agent: userAgent
});

Integration Examples

Node.js/Express

const fetch = require('node-fetch');
 
app.post('/purchase', async (req, res) => {
  const { email, amount, couponCode } = req.body;
 
  // Process payment
  await processPayment(email, amount);
 
  // Track conversion
  const payload = {
    program_id: process.env.REFVENUE_PROGRAM_ID,
    publishable_key: process.env.REFVENUE_KEY,
    conversion_type: 'purchase',
    revenue_amount: amount,
    customer_ip: req.ip,
    customer_user_agent: req.headers['user-agent']
  };
 
  // Use coupon code if provided, otherwise use ref from cookie
  if (couponCode) {
    payload.coupon_code = couponCode;
  } else {
    payload.ref_code = req.cookies.affiliate_ref;
    payload.customer_email = email;
  }
 
  try {
    await fetch('https://tracking.refvenue.com/v1/track-conversion', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
  } catch (error) {
    console.error('Tracking error:', error);
  }
 
  res.json({ success: true });
});

Python/Flask

import requests
 
@app.route('/purchase', methods=['POST'])
def purchase():
    email = request.json['email']
    amount = request.json['amount']
    coupon_code = request.json.get('coupon_code')
 
    # Process payment
    process_payment(email, amount)
 
    # Track conversion
    payload = {
        'program_id': os.environ['REFVENUE_PROGRAM_ID'],
        'publishable_key': os.environ['REFVENUE_KEY'],
        'conversion_type': 'purchase',
        'revenue_amount': amount,
        'customer_ip': request.remote_addr,
        'customer_user_agent': request.headers.get('User-Agent')
    }
 
    if coupon_code:
        payload['coupon_code'] = coupon_code
    else:
        payload['ref_code'] = request.cookies.get('affiliate_ref')
        payload['customer_email'] = email
 
    try:
        requests.post(
            'https://tracking.refvenue.com/v1/track-conversion',
            json=payload
        )
    except Exception as e:
        print(f'Tracking error: {e}')
 
    return {'success': True}

Alternative Methods

Support