Conversions API

Export conversion attribution data with full customer journey tracking. Get first-touch, last-touch, and multi-touch attribution for every conversion.

Endpoint

GET https://app.serp360.ai/api/v1/conversions

Authentication

Pass your API key in the X-API-Key  header:

curl -X GET "https://app.serp360.ai/api/v1/conversions?..." \
  -H "X-API-Key: sk_live_your_key_here"

How it works

The Conversions endpoint uses an immediate pingback flow:

  1. Queue – Call with a pingback_url . We send the pingback immediately and return status ready .
  2. Retrieve – Call again without pingback_url  to fetch the data. Credits are charged here.

Unlike the SERP and Visibility endpoints, conversion data is always ready—there's no ETL delay. We ping you instantly to confirm availability.

Parameters

Parameter Required Description
domain Yes Your domain name (e.g. example.com )
path Yes Conversion path name (case insensitive)
include_journey No Set to true  to include full touchpoint sequence
pingback_url Step 1 only HTTPS URL where we'll POST immediately

Step 1: Queue the request

curl -X GET "https://app.serp360.ai/api/v1/conversions?domain=example.com&path=Purchase%20Complete&include_journey=true&pingback_url=https://your-server.com/webhook" \
  -H "X-API-Key: sk_live_your_key_here"

Response

{
  "success": true,
  "status": "ready",
  "message": "Data is ready. Pingback sent.",
  "request_id": "cpb_123",
  "credits_used": 0,
  "meta": {
    "request_id": "cpb_123",
    "duration_ms": 125.34
  }
}

Note the status is ready  rather than queued —the pingback has already been sent.

Pingback notification

We POST to your pingback_url  immediately:

{
  "event": "conversions_data_ready",
  "domain": "example.com",
  "path": "Purchase Complete",
  "date": "2025-11-29",
  "request_id": "cpb_123",
  "message": "Your conversion data is ready. Call the API without pingback_url to retrieve."
}

Your endpoint should return a 2xx  status. We'll retry failed deliveries up to 3 times.

Step 2: Retrieve the data

Call the same endpoint without pingback_url :

curl -X GET "https://app.serp360.ai/api/v1/conversions?domain=example.com&path=Purchase%20Complete&include_journey=true" \
  -H "X-API-Key: sk_live_your_key_here"

Response

{
  "success": true,
  "data": {
    "domain": "example.com",
    "path": "Purchase Complete",
    "currency": "GBP",
    "date": "2025-11-29",
    "sessions": [
      {
        "session_id": "abc123def456",
        "conversion_timestamp": "2025-11-29T14:32:15Z",
        "revenue": 149.99,
        "is_new_customer": true,
        "conversion_device": "desktop",
        "sessions_to_conversion": 3,
        "days_to_conversion": 12,
        "touchpoint_count": 3,
        "first_touch_timestamp": "2025-11-17T09:15:00Z",
        "first_touch": {
          "channel": "paid_search",
          "source": "google",
          "medium": "cpc",
          "campaign": "black_friday",
          "term": "winter boots sale",
          "content": null,
          "referrer_url": "https://www.google.com/",
          "landing_page_url": "example.com/boots"
        },
        "last_touch": {
          "channel": "email",
          "source": "newsletter",
          "medium": "email",
          "campaign": "cart_reminder",
          "term": null,
          "content": null,
          "referrer_url": null,
          "landing_page_url": "example.com/checkout"
        },
        "journey": [
          {
            "position": 1,
            "channel": "paid_search",
            "source": "google",
            "medium": "cpc",
            "campaign": "black_friday",
            "term": "winter boots sale",
            "content": null,
            "referrer_url": "https://www.google.com/",
            "landing_page_url": "example.com/boots",
            "device": "mobile",
            "timestamp": "2025-11-17T09:15:00Z"
          },
          {
            "position": 2,
            "channel": "organic_search",
            "source": "google",
            "medium": "organic",
            "campaign": null,
            "term": null,
            "content": null,
            "referrer_url": "https://www.google.com/",
            "landing_page_url": "example.com/boots/review",
            "device": "desktop",
            "timestamp": "2025-11-22T19:45:00Z"
          },
          {
            "position": 3,
            "channel": "email",
            "source": "newsletter",
            "medium": "email",
            "campaign": "cart_reminder",
            "term": null,
            "content": null,
            "referrer_url": null,
            "landing_page_url": "example.com/checkout",
            "device": "desktop",
            "timestamp": "2025-11-29T14:30:00Z"
          }
        ]
      }
    ],
    "total_sessions": 1
  },
  "credits_used": 0.5,
  "balance": 63996.5,
  "meta": {
    "request_id": "cpb_124",
    "duration_ms": 89.23
  }
}

Response fields

Top level

Field Type Description
domain string The domain name
path string Conversion path name
currency string Currency code (e.g. GBP, USD, EUR)
date string Date of conversions returned (YYYY-MM-DD)
sessions array Array of conversion sessions
total_sessions integer Number of sessions returned

Session object

Field Type Description
session_id string Unique session identifier
conversion_timestamp string ISO 8601 timestamp of conversion
revenue number Conversion value in the specified currency
is_new_customer boolean First conversion for this visitor
conversion_device string Device type at conversion (desktop, mobile, tablet)
sessions_to_conversion integer Number of sessions before converting
days_to_conversion integer Days from first touch to conversion
touchpoint_count integer Total touchpoints in the journey
first_touch_timestamp string ISO 8601 timestamp of first interaction
first_touch object First-touch attribution data
last_touch object Last-touch attribution data
journey array Full touchpoint sequence (if include_journey=true )

Attribution object (first_touch / last_touch)

Field Type Description
channel string Classified channel (see channel list below)
source string UTM source or inferred source
medium string UTM medium or inferred medium
campaign string|null UTM campaign
term string|null UTM term (search keywords)
content string|null UTM content
referrer_url string|null Full referrer URL
landing_page_url string|null Landing page path

Journey touchpoint object

Field Type Description
position integer Position in journey (1 = first)
channel string Classified channel
source string UTM source or inferred source
medium string UTM medium or inferred medium
campaign string|null UTM campaign
term string|null UTM term
content string|null UTM content
referrer_url string|null Full referrer URL
landing_page_url string Landing page path
device string Device type for this touchpoint
timestamp string ISO 8601 timestamp

Channel classification

Touchpoints are classified into these channels:

Channel Description
organic_search Unpaid search engine traffic
paid_search PPC / Google Ads / Bing Ads
organic_social Unpaid social media
paid_social Paid social campaigns
email Email marketing
referral Links from other websites
direct Direct traffic / bookmarks
display Display advertising
affiliate Affiliate traffic
video YouTube / video platforms
sms SMS campaigns
qr_code QR code scans
other Unclassified traffic

Data notes

  • Latest date only: Returns conversions from the most recent date with data, not historical data.
  • Cookie-based tracking required: Journey data requires cookie-based visitor tracking. Cookieless sessions return an empty journey  array.
  • Omit journey to save bandwidth: If you only need first/last touch attribution, omit include_journey  or set it to false .

Error responses

Domain not found

{
  "success": false,
  "error": "Domain not found or not authorised.",
  "code": "DOMAIN_NOT_FOUND",
  "meta": {
    "request_id": "cpb_125",
    "duration_ms": 12.34
  }
}

Path not found

{
  "success": false,
  "error": "Conversion path not found.",
  "code": "PATH_NOT_FOUND",
  "meta": {
    "request_id": "cpb_126",
    "duration_ms": 10.56
  }
}

No conversions

{
  "success": false,
  "error": "No conversion data available for this path.",
  "code": "NO_DATA",
  "meta": {
    "request_id": "cpb_127",
    "duration_ms": 15.67
  }
}

Pricing

0.5 credits per successful retrieval.

Credits are charged when you retrieve data in step 2, regardless of how many sessions are returned.

Example: Python integration

import requests

API_KEY = "sk_live_your_key_here"
BASE_URL = "https://app.serp360.ai/api/v1/conversions"

def queue_conversions_request(domain, path, pingback_url, include_journey=False):
    """Queue a conversions data request."""
    params = {
        "domain": domain,
        "path": path,
        "pingback_url": pingback_url,
        "include_journey": str(include_journey).lower()
    }
    
    response = requests.get(
        BASE_URL,
        headers={"X-API-Key": API_KEY},
        params=params
    )
    return response.json()

def retrieve_conversions(domain, path, include_journey=False):
    """Retrieve conversion data after pingback received."""
    params = {
        "domain": domain,
        "path": path,
        "include_journey": str(include_journey).lower()
    }
    
    response = requests.get(
        BASE_URL,
        headers={"X-API-Key": API_KEY},
        params=params
    )
    return response.json()

# Queue the request
result = queue_conversions_request(
    domain="example.com",
    path="Purchase Complete",
    pingback_url="https://your-server.com/webhook",
    include_journey=True
)
print(f"Status: {result['status']}")  # "ready"

# Retrieve immediately (or after pingback)
data = retrieve_conversions(
    domain="example.com",
    path="Purchase Complete",
    include_journey=True
)

# Process conversions
for session in data['data']['sessions']:
    print(f"\nConversion: {session['conversion_timestamp']}")
    print(f"Revenue: {data['data']['currency']} {session['revenue']}")
    print(f"First touch: {session['first_touch']['channel']}")
    print(f"Last touch: {session['last_touch']['channel']}")
    print(f"Journey length: {session['touchpoint_count']} touchpoints over {session['days_to_conversion']} days")

Example: Channel attribution analysis

def analyse_channel_attribution(data):
    """Analyse first-touch vs last-touch channel performance."""
    first_touch_revenue = {}
    last_touch_revenue = {}
    
    currency = data['data']['currency']
    
    for session in data['data']['sessions']:
        revenue = session['revenue']
        
        # First touch attribution
        ft_channel = session['first_touch']['channel']
        first_touch_revenue[ft_channel] = first_touch_revenue.get(ft_channel, 0) + revenue
        
        # Last touch attribution
        lt_channel = session['last_touch']['channel']
        last_touch_revenue[lt_channel] = last_touch_revenue.get(lt_channel, 0) + revenue
    
    return {
        "currency": currency,
        "first_touch": first_touch_revenue,
        "last_touch": last_touch_revenue
    }

# Usage
data = retrieve_conversions(domain="example.com", path="Purchase Complete")
attribution = analyse_channel_attribution(data)

print(f"First-touch attribution ({attribution['currency']}):")
for channel, revenue in sorted(attribution['first_touch'].items(), key=lambda x: -x[1]):
    print(f"  {channel}: {revenue:.2f}")

print(f"\nLast-touch attribution ({attribution['currency']}):")
for channel, revenue in sorted(attribution['last_touch'].items(), key=lambda x: -x[1]):
    print(f"  {channel}: {revenue:.2f}")

Example: Journey path analysis

def analyse_journey_paths(data, min_occurrences=2):
    """Find common conversion paths."""
    from collections import Counter
    
    paths = []
    
    for session in data['data']['sessions']:
        if session.get('journey'):
            # Create path string from channels
            path = " → ".join([tp['channel'] for tp in session['journey']])
            paths.append(path)
    
    # Count occurrences
    path_counts = Counter(paths)
    
    # Filter by minimum occurrences
    common_paths = {
        path: count 
        for path, count in path_counts.items() 
        if count >= min_occurrences
    }
    
    return common_paths

# Usage
data = retrieve_conversions(
    domain="example.com", 
    path="Purchase Complete",
    include_journey=True
)

paths = analyse_journey_paths(data, min_occurrences=2)
print("Common conversion paths:")
for path, count in sorted(paths.items(), key=lambda x: -x[1]):
    print(f"  {path}: {count} conversions")

Example: Webhook handler (Node.js/Express)

const express = require('express');
const app = express();

app.use(express.json());

app.post('/webhook', (req, res) => {
  const { event, domain, path, date } = req.body;
  
  if (event === 'conversions_data_ready') {
    console.log(`Conversion data ready for ${domain} / ${path}`);
    console.log(`Date: ${date}`);
    
    // Trigger your data retrieval process
    // Note: For conversions, this fires immediately after queuing
  }
  
  res.status(200).send('OK');
});

app.listen(3000);

Tips

  • Use include_journey selectively – Full journey data increases response size. Omit it if you only need first/last touch.
  • Daily exports – Call the API once per day to get yesterday's conversions. The endpoint returns the latest date's data.
  • Cross-device journeys – The device  field in journey touchpoints shows when users switch devices during their path to conversion.
  • New vs returning – Use is_new_customer  to segment first-time buyers from repeat purchasers.
  • Calculate time to convertdays_to_conversion  and sessions_to_conversion  help you understand your sales cycle length.
Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.