Skip to content
  • There are no suggestions because the search field is empty.

Complete Guide: Creating Custom Integrations with Convert.com

Guide to help you build integrations with Convert.com

Author: George F. Crewe

IN THIS ARTICLE YOU WILL:

This guide provides a standardized approach for connecting Convert.com to your internal backend or third-party analytics platforms. It uses a stable visitor identifier so that frontend experiment exposure and backend conversions can be tied to the same visitor.

This guide uses Convert’s current Experiences Tracking API for backend conversion tracking. For standard tracking requests, the endpoint is POST https://metrics.convertexperiments.com/v1/track/{account_id}/{project_id}. SDK-key based tracking is also available through POST https://metrics.convertexperiments.com/v1/track/{sdk_key}

1. Frontend: Implementing Bring Your Own ID (BYOID)

To ensure 100% data consistency between your backend and Convert.com, you should use your own internal identifier (like a Database User ID or a hashed email) instead of relying on Convert's default cookies.

Crucial: Sequence of Execution

The BYOID must be defined before the main Convert tracking tag loads on your page. This ensures that the very first "bucket" event recorded by Convert is already associated with your custom ID.

Correct Implementation Order:

<script>
  window._conv_q = window._conv_q || [];
  window._conv_q.push({
    what: 'identify',
    params: {
      visitorId: 'YOUR_INTERNAL_USER_ID' // Replace with your actual dynamic, non-PII ID
    }
  });
</script>

<script type="text/javascript" src="//cdn-4.convertexperiments.com/v1/js/12345678-12345678.js"></script>

⚠️ Important:

Use a stable, opaque, non-PII value. Do not pass raw emails, phone numbers, names, or other directly identifiable personal data as the visitor ID.

 

2. Frontend: Extracting Data and Segments

Use Convert’s visitor-data helper methods to extract the visitor ID, active bucketing data, and visitor segments. This allows you to forward Convert’s data to third-party tools, such as Segment, Mixpanel, or GA4, using your own identifier.

const convert_utils = {
  getBrowser: () => window.convert?.currentData?.segments?.browser || 'OTH',
  getDevice: () => window.convert?.currentData?.segments?.devices || ['OTHDEV'],
  getSource: () => window.convert?.currentData?.segments?.source || 'direct',
  getVisitorType: () => window.convert?.currentData?.segments?.visitorType || 'new',
  getCountry: () => window.convert?.currentData?.segments?.country || '',
  getCampaign: () => window.convert?.currentData?.segments?.campaign || '',
  getCustomSegments: () => window.convert?.currentData?.segments?.customSegments || []
};

// Listener: Fires when experiences are evaluated
window._conv_q = window._conv_q || [];

window._conv_q.push({
  what: 'addListener',
  params: {
    event: 'snippet.experiences_evaluated',
    handler: function() {
      const visitorData = window.convert?.getCurrentVisitorData?.() || {};
      const segments =
        visitorData.segments ||
        window.convert?.getVisitorSegments?.() ||
        {};

      const bucketing = Array.isArray(visitorData.bucketing)
        ? visitorData.bucketing
        : [];

      const dataPayload = {
        visitorId: visitorData.visitorId,
        experiences: bucketing.map(function(item) {
          return {
            experienceId: String(item.experienceId || ''),
            variationId: String(item.variationId || '')
          };
        }),
        segments: {
          browser: segments.browser || 'OTH',
          devices: segments.devices || ['OTHDEV'],
          source: segments.source || 'direct',
          visitorType: segments.visitorType || 'new',
          country: segments.country || '',
          campaign: segments.campaign || '',
          customSegments: segments.customSegments || []
        }
      };

      // Action: Forward this to your backend or third-party analytics tool.
      // myAnalyticsApp.track('Convert Data', dataPayload);
      // sendToBackend('/convert-context', dataPayload);
    }
  }
});

Store visitorId, experienceId, variationId, and relevant segments in your backend or CRM so they can be reused later when a backend conversion occurs.

 

3. API Mapping Table (Segment Codes)

When sending data via the Experiences Tracking API, use the supported segment fields and values.

Category Field Supported Values / Format Description
Browser browser IE, CH, FF, OP, SF, OTH Internet Explorer/Edge, Chrome, Firefox, Opera, Safari, Other
Devices devices ALLPH, IPH, OTHPH, ALLTAB, IPAD, OTHTAB, DESK, OTHDEV Phone, tablet, desktop, or other device categories
Source source campaign, search, referral, direct, ai_tool Traffic origin category
Visitor Type visitorType new, returning Visitor status
Country country Two-letter ISO country code, e.g. US, GB, DE Visitor country
Campaign campaign String Campaign identifier
Custom Segments customSegments Array of custom segment IDs Custom segment references

 

 

4. Backend: Tracking Conversions — Experiences Tracking API

When a conversion occurs on your server, such as a processed payment, lead qualification, subscription activation, or CRM status change, use Convert’s Experiences Tracking API to send the conversion event.

API Endpoint

POST https://metrics.convertexperiments.com/v1/track/{account_id}/{project_id}

Alternative SDK-key endpoint:

POST https://metrics.convertexperiments.com/v1/track/{sdk_key}

Request Headers:

  • Content-Type: application/json

Request Body (JSON):

{
  "accountId": "10012345",
  "projectId": "10056789",
  "enrichData": true,
  "visitors": [
    {
      "visitorId": "YOUR_INTERNAL_USER_ID",
      "segments": {
        "browser": "CH",
        "devices": ["DESK"],
        "source": "direct",
        "visitorType": "new",
        "country": "US",
        "customSegments": ["segment-id-1", "segment-id-2"]
      },
      "events": [
        {
          "eventType": "conversion",
          "data": {
            "goalId": "99887766",
            "bucketingData": {
              "11223344": "55667788"
            },
            "goalData": [
              { "key": "amount", "value": 99.99 },
              { "key": "productsCount", "value": 2 },
              { "key": "transactionId", "value": "TXN-12345" }
            ]
          }
        }
      ]
    }
  ]
}

In bucketingData, the object key is the experienceId and the value is the variationId:

{
  "experienceId": "variationId"
}

Example:

{
  "100127238": "1001186427"
}

Available Goal Data Keys

Use goalData when you need to send revenue, product count, transaction IDs, or custom reporting dimensions.

Key Value Type Description
amount Number Revenue amount
productsCount Number Number of products
transactionId String Transaction identifier
customDimension1customDimension5 String or array Custom dimension values. Array values are accepted only for customDimension1customDimension5; each item is limited to 32 characters, and longer values may be truncated.

 

5. Backend Code Example — Python

import requests


def send_conversion_to_convert(
    account_id,
    project_id,
    visitor_id,
    experience_id,
    variation_id,
    goal_id,
    segments=None,
    goal_data=None
):
    """
    Send a backend conversion event to Convert.

    Args:
        account_id: Convert account ID.
        project_id: Convert project ID.
        visitor_id: The same visitor ID used on the frontend.
        experience_id: Convert experience ID.
        variation_id: Convert variation ID.
        goal_id: Convert goal ID.
        segments: Optional visitor segment data.
        goal_data: Optional goal data such as revenue or transaction ID.
    """

    url = f"https://metrics.convertexperiments.com/v1/track/{account_id}/{project_id}"

    event_data = {
        "goalId": str(goal_id),
        "bucketingData": {
            str(experience_id): str(variation_id)
        }
    }

    if goal_data:
        event_data["goalData"] = goal_data

    payload = {
        "accountId": str(account_id),
        "projectId": str(project_id),
        "enrichData": True,
        "visitors": [
            {
                "visitorId": str(visitor_id),
                "segments": segments or {},
                "events": [
                    {
                        "eventType": "conversion",
                        "data": event_data
                    }
                ]
            }
        ]
    }

    response = requests.post(url, json=payload)
    response.raise_for_status()

    return response.status_code == 200


# Usage example
send_conversion_to_convert(
    account_id="10007679",
    project_id="10007855",
    visitor_id="visitor-abc123",
    experience_id="100127238",
    variation_id="1001186427",
    goal_id="100037225",
    segments={
        "visitorType": "new",
        "browser": "CH",
        "devices": ["DESK"],
        "source": "direct",
        "country": "US"
    },
    goal_data=[
        {"key": "amount", "value": 149.99},
        {"key": "productsCount", "value": 3},
        {"key": "transactionId", "value": "ORDER-12345"}
    ]
)

6. Backend Code Example — Node.js

async function sendConversionToConvert({
  accountId,
  projectId,
  visitorId,
  experienceId,
  variationId,
  goalId,
  segments = {},
  goalData = []
}) {
  const url = `https://metrics.convertexperiments.com/v1/track/${accountId}/${projectId}`;

  const eventData = {
    goalId: String(goalId),
    bucketingData: {
      [String(experienceId)]: String(variationId)
    }
  };

  if (goalData.length) {
    eventData.goalData = goalData;
  }

  const payload = {
    accountId: String(accountId),
    projectId: String(projectId),
    enrichData: true,
    visitors: [
      {
        visitorId: String(visitorId),
        segments,
        events: [
          {
            eventType: "conversion",
            data: eventData
          }
        ]
      }
    ]
  };

  const response = await fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify(payload)
  });

  if (!response.ok) {
    const errorBody = await response.text();
    throw new Error(`Convert tracking failed: ${response.status} ${errorBody}`);
  }

  return response.json();
}


// Usage example
sendConversionToConvert({
  accountId: "10007679",
  projectId: "10007855",
  visitorId: "visitor-abc123",
  experienceId: "100127238",
  variationId: "1001186427",
  goalId: "100037225",
  segments: {
    visitorType: "new",
    browser: "CH",
    devices: ["DESK"],
    source: "direct",
    country: "US"
  },
  goalData: [
    { key: "amount", value: 149.99 },
    { key: "productsCount", value: 3 },
    { key: "transactionId", value: "ORDER-12345" }
  ]
});

7. Backend Code Example — PHP

<?php

function sendConversionToConvert(
    $accountId,
    $projectId,
    $visitorId,
    $experienceId,
    $variationId,
    $goalId,
    $segments = [],
    $goalData = []
) {
    $url = "https://metrics.convertexperiments.com/v1/track/{$accountId}/{$projectId}";

    $eventData = [
        "goalId" => (string) $goalId,
        "bucketingData" => [
            (string) $experienceId => (string) $variationId
        ]
    ];

    if (!empty($goalData)) {
        $eventData["goalData"] = $goalData;
    }

    $payload = [
        "accountId" => (string) $accountId,
        "projectId" => (string) $projectId,
        "enrichData" => true,
        "visitors" => [
            [
                "visitorId" => (string) $visitorId,
                "segments" => $segments,
                "events" => [
                    [
                        "eventType" => "conversion",
                        "data" => $eventData
                    ]
                ]
            ]
        ]
    ];

    $options = [
        "http" => [
            "header" => "Content-Type: application/json\r\n",
            "method" => "POST",
            "content" => json_encode($payload)
        ]
    ];

    $context = stream_context_create($options);
    $result = file_get_contents($url, false, $context);

    return $result !== false;
}


// Usage example
sendConversionToConvert(
    "10007679",
    "10007855",
    "visitor-abc123",
    "100127238",
    "1001186427",
    "100037225",
    [
        "visitorType" => "new",
        "browser" => "CH",
        "devices" => ["DESK"],
        "source" => "direct",
        "country" => "US"
    ],
    [
        ["key" => "amount", "value" => 149.99],
        ["key" => "productsCount", "value" => 3],
        ["key" => "transactionId", "value" => "ORDER-12345"]
    ]
);

8. Best Practices

  • Persistent Identity: Setting BYOID before the Convert tag helps ensure that bucketing and conversion events are tied to the same visitor identity.
  • Use the same visitorId in all places: frontend identity, analytics payloads, backend storage, and backend conversion tracking.
  • Store Bucketing Data: When the visitor is evaluated for experiences, store the experienceId and variationId along with the visitor ID. Backend conversions need this data to populate bucketingData.
  • Use eventType: "conversion" for conversion events.
  • Use goalData for Revenue: When tracking purchases, include goalData for amount, productsCount, and transactionId so revenue and transaction data can be attributed correctly.
  • Use enrichData Carefully: The enrichData flag can enrich events before they are stored for reporting, for example by using backend datastore bucketing or segments when not provided in the request. Availability may depend on the plan.

9. Troubleshooting

Conversion does not appear in reports

Check that:

The visitorId matches the same ID used when the visitor was bucketed.
The goalId belongs to the project and is attached where needed.
The experienceId and variationId are correct.
The bucketingData object maps experience ID to variation ID.
The request is sent as POST with Content-Type: application/json.

Revenue is missing

Check that:

goalData includes amount as a number.
transactionId is unique for the order.
Revenue tracking is supported and configured for the relevant goal/reporting setup.

Visitor segmentation is missing

Check that:

Segments are sent under visitors[].segments.
visitorType uses new or returning, not 0 or 1.
devices is an array, for example ["DESK"].