Complete Guide: Creating Integrations with Convert.com
Guide to help you build integrations with Convert.com
Author: George F. Crewe
THIS ARTICLE WILL HELP YOU:
- Understand Integration Type 1: Sending Experiment Data to Analytics Platforms
- Understand Integration Type 2: Sending Backend Conversions to Convert
- Know Some Key Resources
This comprehensive guide will help you build integrations with Convert.com for two primary use cases: sending experiment data to analytics platforms and tracking backend conversions.
Integration Type 1: Sending Experiment Data to Analytics Platforms
Overview
This integration allows you to capture Convert.com experiment data in real-time and forward it to third-party analytics platforms (like Google Analytics, Heap, Mixpanel, etc.).
How It Works
Convert.com provides JavaScript objects that contain experiment and variation data whenever a visitor is bucketed into an experiment. You can read this data and push it to your analytics platform.
Key JavaScript Objects
1. convert.currentData
Contains data for experiences (experiments) and goals triggered on the current page.
Structure:
{
"experiences": {
"100127238": {
"firstTime": false,
"variation": {
"changes": [
{
"name": "Variation"
}
],
"id": "1001186427",
"name": "Variation",
"key": "1001186427-variation",
"status": "running",
"traffic_allocation": 50
}
},
"100127280": {
"firstTime": false,
"variation": {
"changes": [
{
"name": "Deployment"
}
],
"id": "1001186515",
"name": "Deployment",
"key": "1001186515-deployment",
"status": "running",
"traffic_allocation": 100
}
}
},
"experiencesGoals": {},
"goals": {}
}
Key Fields:
- experiences: Object containing all active experiments on the current page
- Experience ID (e.g., "100127238"): Unique identifier for the experience/experiment
- firstTime: Boolean indicating if this is the visitor's first exposure to this experiment
- variation: Object containing variation details
- id: Unique variation ID
- name: Human-readable variation name (anonymized if data anonymization is enabled)
- key: Unique key combining variation ID and name
- status: Current status of the variation (e.g., "running")
- traffic_allocation: Percentage of traffic allocated to this variation
- changes: Array of change objects, each containing:
- name: Name of the change/section
- goals: Object containing goals triggered on the current page (goal IDs as keys, value of 1)
- experiencesGoals: Object mapping experiences to their triggered goals
2. convert.historicalData
Contains all experiment data across the visitor's entire session history.
Structure:
{
"experiences": {
"100127238": {
"variation_name": "Variation",
"variationName": "Variation",
"variation_id": 1001186427,
"variationId": 1001186427,
"goals": {
"100132206": 1
}
},
"100127280": {
"variation_name": "Deployment",
"variationName": "Deployment",
"variation_id": 1001186515,
"variationId": 1001186515,
"goals": {}
}
}
}
Key Fields:
- experiences: Object containing all experiments the visitor has been exposed to
- Experience ID: Unique identifier for the experience
- variationName / variation_name: Name of the variation (both formats provided for compatibility)
- variationId / variation_id: ID of the variation (both formats provided for compatibility)
- goals: Object containing all goals triggered for this experience (goal IDs as keys, value of 1)
Implementation Best Practices
Use the Convert Queue (convq)
Since some experiments trigger asynchronously (e.g., geo-targeted experiments), always read experiment data within the Convert queue to ensure all data is available:
_conv_q = _conv_q || [];
_conv_q.push([function(){
// Your integration code here
var currentData = convert.currentData;
var historicalData = convert.historicalData;
// Process and send data to your analytics platform
sendToAnalytics(currentData);
}]);
Step-by-Step Implementation
Step 1: Set up the queue function
_conv_q = _conv_q || [];
_conv_q.push([function(){
// Code executes after all experiments are triggered
}]);
Step 2: Extract experiment data from convert.currentData
_conv_q.push([function(){
var experiences = convert.currentData.experiences;
for (var expId in experiences) {
var experience = experiences[expId];
var experimentId = expId;
var variationId = experience.variation.id;
var variationName = experience.variation.name;
var variationKey = experience.variation.key;
var isFirstTime = experience.firstTime;
var trafficAllocation = experience.variation.traffic_allocation;
// Use this data in your integration
}
}]);
Step 3: Extract experiment data from convert.historicalData
_conv_q.push([function(){
var historicalExperiences = convert.historicalData.experiences;
for (var expId in historicalExperiences) {
var experience = historicalExperiences[expId];
var experimentId = expId;
// Both formats are available for compatibility
var variationId = experience.variationId; // or experience.variation_id
var variationName = experience.variationName; // or experience.variation_name
var goals = experience.goals;
// Use this data to understand visitor's full experiment history
}
}]);
Step 4: Send data to your analytics platform
_conv_q.push([function(){
var experiences = convert.currentData.experiences;
for (var expId in experiences) {
var exp = experiences[expId];
var variation = exp.variation;
// Example: Send to Google Analytics
ga('send', 'event', 'Convert', 'Experiment-' + expId, variation.name);
// Example: Send to custom analytics
yourAnalytics.track('Experiment Viewed', {
experiment_id: expId,
variation_id: variation.id,
variation_name: variation.name,
variation_key: variation.key,
first_time: exp.firstTime,
traffic_allocation: variation.traffic_allocation,
status: variation.status
});
}
}]);
Real-World Example: Heap Analytics Integration
Here's a complete example based on the Heap Analytics integration pattern:
_conv_q = _conv_q || [];
_conv_q.push([function(){
// Get current experiment data
var experiences = convert.currentData.experiences;
// Loop through all active experiments
for (var experienceId in experiences) {
if (experiences.hasOwnProperty(experienceId)) {
var experienceData = experiences[experienceId];
var variation = experienceData.variation;
// Send to Heap as user properties
heap.addUserProperties({
['Convert_Experiment_' + experienceId]: variation.name,
['Convert_Variation_ID_' + experienceId]: variation.id,
['Convert_Variation_Key_' + experienceId]: variation.key
});
// Track event
heap.track('Convert Experiment Viewed', {
experiment_id: experienceId,
variation_id: variation.id,
variation_name: variation.name,
variation_key: variation.key,
first_time: experienceData.firstTime,
traffic_allocation: variation.traffic_allocation,
status: variation.status
});
}
}
// Track goals if any were triggered
var goals = convert.currentData.goals;
for (var goalId in goals) {
if (goals.hasOwnProperty(goalId)) {
heap.track('Convert Goal Triggered', {
goal_id: goalId
});
}
}
}]);
Advanced Example: Using Historical Data
_conv_q = _conv_q || [];
_conv_q.push([function(){
// Send historical experiment data as user properties
var historicalExperiences = convert.historicalData.experiences;
var userProperties = {};
for (var expId in historicalExperiences) {
if (historicalExperiences.hasOwnProperty(expId)) {
var exp = historicalExperiences[expId];
// Add to user properties
userProperties['Convert_Historical_Exp_' + expId] = exp.variationName;
userProperties['Convert_Historical_Var_ID_' + expId] = exp.variationId;
// Track goals triggered for this experiment
var goalCount = Object.keys(exp.goals).length;
userProperties['Convert_Goal_Count_' + expId] = goalCount;
}
}
// Send to your analytics platform
if (typeof heap !== 'undefined') {
heap.addUserProperties(userProperties);
}
if (typeof analytics !== 'undefined') {
analytics.identify(userProperties);
}
}]);
Advanced Example: Multiple Analytics Platforms
_conv_q = _conv_q || [];
_conv_q.push([function(){
var experiences = convert.currentData.experiences;
for (var expId in experiences) {
if (experiences.hasOwnProperty(expId)) {
var exp = experiences[expId];
var variation = exp.variation;
// Google Analytics 4
if (typeof gtag !== 'undefined') {
gtag('event', 'experiment_impression', {
experiment_id: expId,
variation_id: variation.id,
variation_name: variation.name
});
}
// Segment
if (typeof analytics !== 'undefined') {
analytics.track('Experiment Viewed', {
experiment_id: expId,
variation_id: variation.id,
variation_name: variation.name,
first_time: exp.firstTime
});
}
// Mixpanel
if (typeof mixpanel !== 'undefined') {
mixpanel.track('Experiment Viewed', {
'Experiment ID': expId,
'Variation ID': variation.id,
'Variation Name': variation.name,
'First Time': exp.firstTime
});
mixpanel.people.set({
['Experiment_' + expId]: variation.name
});
}
// Adobe Analytics
if (typeof s !== 'undefined') {
s.eVar10 = expId + ':' + variation.name;
s.tl(true, 'o', 'Convert Experiment');
}
}
}
}]);
Where to Place the Code
You can place this code in:
- Convert Project Configuration → Global JavaScript
- Google Tag Manager → Custom HTML tag
- Directly in your website's code (before closing </body> tag)
Important: The code can be placed anywhere on the page because the _conv_q queue ensures it executes at the right time.
Integration Type 2: Sending Backend Conversions to Convert
Overview
This integration allows you to track conversions that happen on your backend (server-side) and send them to Convert.com via REST API.
Use Cases
- Payment confirmations processed server-side
- Subscription activations
- Backend form submissions
- API-based conversions
- Events that occur outside the browser
Implementation Architecture
Frontend (Experiment Page):
- Capture Convert experiment data using JavaScript objects
- Store this data (cookie, localStorage, or send to backend)
Backend (Conversion Point):
- Retrieve the stored experiment data
- Send conversion event to Convert.com via REST API
Step 1: Capture Experiment Data on Frontend
On the page where the experiment runs, capture the necessary data using the new structure:
_conv_q = _conv_q || [];
_conv_q.push([function(){
var experiences = convert.currentData.experiences;
var experimentData = [];
// Collect experiment and variation data
for (var expId in experiences) {
if (experiences.hasOwnProperty(expId)) {
var experience = experiences[expId];
experimentData.push({
experiment_id: expId,
variation_id: experience.variation.id,
variation_name: experience.variation.name,
variation_key: experience.variation.key
});
}
}
// Get visitor ID (Convert's unique visitor identifier)
var visitorId = convert.visitorId;
// Store data for backend use
// Option 1: Cookie
document.cookie = "convert_data=" + JSON.stringify({
visitor_id: visitorId,
experiences: experimentData
}) + "; path=/; max-age=86400"; // 24 hours
// Option 2: Send to backend immediately
fetch('/api/store-convert-data', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
visitor_id: visitorId,
experiences: experimentData
})
});
// Option 3: localStorage
localStorage.setItem('convert_data', JSON.stringify({
visitor_id: visitorId,
experiences: experimentData
}));
}]);
Alternative: Capture from Historical Data
You can also use convert.historicalData to ensure you capture all experiments the visitor has seen:
_conv_q = _conv_q || [];
_conv_q.push([function(){
var historicalExperiences = convert.historicalData.experiences;
var experimentData = [];
// Collect all historical experiment and variation data
for (var expId in historicalExperiences) {
if (historicalExperiences.hasOwnProperty(expId)) {
var experience = historicalExperiences[expId];
experimentData.push({
experiment_id: expId,
variation_id: experience.variationId, // or experience.variation_id
variation_name: experience.variationName // or experience.variation_name
});
}
}
// Get visitor ID
var visitorId = convert.visitorId;
// Store data
document.cookie = "convert_data=" + JSON.stringify({
visitor_id: visitorId,
experiences: experimentData
}) + "; path=/; max-age=86400";
}]);
Step 2: Send Conversion from Backend
When a conversion occurs on your backend, use the Convert.com REST API to track it.
API Endpoint Structure
https://data.convert.com/track/{PROJECT_ID}/{VISITOR_ID}?s={EVENTS}
Required Parameters
- PROJECT_ID: Your Convert project ID
- VISITOR_ID: The unique visitor ID captured from frontend
- EVENTS: URL-encoded event string with experiment and goal data
Event Structure for hitGoal
{
"events": [
{
"type": "hitGoal",
"data": {
"expId": "experiment_id",
"varId": "variation_id",
"goalId": "goal_id"
}
}
]
}
Backend Implementation Examples
Python Example
import requests
import json
from urllib.parse import quote
def send_conversion_to_convert(project_id, visitor_id, experiment_id, variation_id, goal_id):
"""
Send a conversion event to Convert.com
Args:
project_id: Your Convert.com project ID
visitor_id: Unique visitor ID from convert.visitorId
experiment_id: Experience/Experiment ID
variation_id: Variation ID (from experience.variation.id)
goal_id: Goal ID to trigger
"""
# Build event data
events = [{
"type": "hitGoal",
"data": {
"expId": str(experiment_id),
"varId": str(variation_id),
"goalId": str(goal_id)
}
}]
# URL encode the events
events_param = quote(json.dumps(events))
# Build the URL
url = f"https://data.convert.com/track/{project_id}/{visitor_id}?s={events_param}"
# Send the request
response = requests.get(url)
return response.status_code == 200
# Usage example
# Data retrieved from cookie/database that was stored on frontend
convert_data = {
'visitor_id': 'abc123xyz',
'experiences': [
{
'experiment_id': '100127238',
'variation_id': '1001186427',
'variation_name': 'Variation'
},
{
'experiment_id': '100127280',
'variation_id': '1001186515',
'variation_name': 'Deployment'
}
]
}
# When conversion happens, send for all experiences
for experience in convert_data['experiences']:
send_conversion_to_convert(
project_id="10012345",
visitor_id=convert_data['visitor_id'],
experiment_id=experience['experiment_id'],
variation_id=experience['variation_id'],
goal_id="100132206" # Your goal ID
)
Node.js Example
const axios = require('axios');
async function sendConversionToConvert(projectId, visitorId, experimentId, variationId, goalId) {
/**
* Send a conversion event to Convert.com
*
* @param {string} projectId - Your Convert.com project ID
* @param {string} visitorId - Unique visitor ID from convert.visitorId
* @param {string} experimentId - Experience/Experiment ID
* @param {string} variationId - Variation ID (from experience.variation.id)
* @param {string} goalId - Goal ID to trigger
*/
const events = [{
type: "hitGoal",
data: {
expId: experimentId.toString(),
varId: variationId.toString(),
goalId: goalId.toString()
}
}];
const eventsParam = encodeURIComponent(JSON.stringify(events));
const url = `https://data.convert.com/track/${projectId}/${visitorId}?s=${eventsParam}`;
try {
const response = await axios.get(url);
return response.status === 200;
} catch (error) {
console.error('Error sending conversion:', error);
return false;
}
}
// Usage example
// Data retrieved from cookie/database that was stored on frontend
const convertData = {
visitor_id: 'abc123xyz',
experiences: [
{
experiment_id: '100127238',
variation_id: '1001186427',
variation_name: 'Variation',
variation_key: '1001186427-variation'
},
{
experiment_id: '100127280',
variation_id: '1001186515',
variation_name: 'Deployment',
variation_key: '1001186515-deployment'
}
]
};
// When conversion happens
async function trackBackendConversion(goalId) {
for (const experience of convertData.experiences) {
await sendConversionToConvert(
'10012345', // projectId
convertData.visitor_id, // visitorId
experience.experiment_id, // experimentId
experience.variation_id, // variationId
goalId // goalId
);
}
}
// Track conversion for specific goal
trackBackendConversion('100132206');
PHP Example
<?php
/**
* Send a conversion event to Convert.com
*
* @param string $projectId Your Convert.com project ID
* @param string $visitorId Unique visitor ID from convert.visitorId
* @param string $experimentId Experience/Experiment ID
* @param string $variationId Variation ID (from experience.variation.id)
* @param string $goalId Goal ID to trigger
* @return bool Success status
*/
function sendConversionToConvert($projectId, $visitorId, $experimentId, $variationId, $goalId) {
$events = [
[
"type" => "hitGoal",
"data" => [
"expId" => (string)$experimentId,
"varId" => (string)$variationId,
"goalId" => (string)$goalId
]
]
];
$eventsParam = urlencode(json_encode($events));
$url = "https://data.convert.com/track/{$projectId}/{$visitorId}?s={$eventsParam}";
$response = @file_get_contents($url);
return $response !== false;
}
// Usage example
// Data retrieved from cookie/database that was stored on frontend
$convertData = json_decode($_COOKIE['convert_data'], true);
// When conversion happens, send for all experiences
foreach ($convertData['experiences'] as $experience) {
sendConversionToConvert(
'10012345', // projectId
$convertData['visitor_id'], // visitorId
$experience['experiment_id'], // experimentId
$experience['variation_id'], // variationId
'100132206' // goalId
);
}
?>
Ruby Example
require 'net/http'
require 'json'
require 'uri'
def send_conversion_to_convert(project_id, visitor_id, experiment_id, variation_id, goal_id)
# Build event data
events = [{
type: "hitGoal",
data: {
expId: experiment_id.to_s,
varId: variation_id.to_s,
goalId: goal_id.to_s
}
}]
# URL encode the events
events_param = URI.encode_www_form_component(events.to_json)
# Build the URL
url = URI("https://data.convert.com/track/#{project_id}/#{visitor_id}?s=#{events_param}")
# Send the request
response = Net::HTTP.get_response(url)
response.is_a?(Net::HTTPSuccess)
end
# Usage example
convert_data = {
visitor_id: 'abc123xyz',
experiences: [
{
experiment_id: '100127238',
variation_id: 1001186427,
variation_name: 'Variation'
},
{
experiment_id: '100127280',
variation_id: 1001186515,
variation_name: 'Deployment'
}
]
}
# When conversion happens, send for all experiences
convert_data[:experiences].each do |experience|
send_conversion_to_convert(
'10012345', # project_id
convert_data[:visitor_id], # visitor_id
experience[:experiment_id], # experiment_id
experience[:variation_id], # variation_id
'100132206' # goal_id
)
end
Complete Integration Flow
- Visitor lands on experiment page
- Convert.com buckets visitor into variation
- Your code captures experiment data via convert.currentData.experiences
- Extract experience ID and variation.id from the experience object
- Store visitor ID and experience/variation data
- Visitor completes action
- Action triggers backend process (e.g., completes checkout)
- Backend retrieves stored Convert data (visitor ID, experience ID, variation ID)
- Backend sends conversion
- Backend makes REST API call to Convert.com
- Includes visitor ID, experience ID, variation ID, and goal ID
- Convert.com records the conversion
Important Considerations
Data Persistence:
- Ensure experiment data persists from frontend to backend
- Use cookies with appropriate expiration (e.g., 24 hours or session-based)
- Or store in user session/database linked to user session
Variation ID Format:
- Use experience.variation.id from convert.currentData
- Or use experience.variationId (or experience.variation_id) from convert.historicalData
- Store as string to prevent type conversion issues
Error Handling:
- Implement retry logic for failed API calls
- Log failures for debugging
- Don't block business logic if Convert tracking fails
Multiple Experiments:
- Visitor may be in multiple experiments/experiences
- Send separate hitGoal events for each experiment
- Loop through all experiences in convert.currentData.experiences or convert.historicalData.experiences
Data Structure Mapping:
// Frontend capture from convert.currentData
convert.currentData.experiences[experienceId].variation.id → variationId
// Frontend capture from convert.historicalData
convert.historicalData.experiences[experienceId].variationId → variationId
// or
convert.historicalData.experiences[experienceId].variation_id → variationId
// Backend API call
expId: experienceId
varId: variationId // from experience.variation.id or experience.variationId
goalId: your_goal_id
Key Resources
Documentation Links
- Reading Experiment Data (JavaScript Objects)
- Reading Triggered Experiment Data
- Covers convert.currentData and convert.historicalData
- Example Integration
- Heap Analytics Integration
- Real-world example with complete code
- Backend Conversion Tracking (REST API)
- New Tracking Structure - Advanced Integrations
- REST API documentation for hitGoal events
Quick Reference
JavaScript Objects (New Structure):
convert.currentData:
- convert.currentData.experiences - Object containing active experiments
- Each experience has: firstTime, variation object
- Variation contains: id, name, key, status, traffic_allocation, changes
- convert.currentData.goals - Goals triggered on current page
- convert.currentData.experiencesGoals - Mapping of experiences to goals
convert.historicalData:
- convert.historicalData.experiences - All experiments visitor has seen
- Each experience has: variationName/variation_name, variationId/variation_id, goals
- Both camelCase and snake_case formats available for compatibility
Other Objects:
- convert.visitorId - Unique visitor identifier
- _conv_q - Queue for ensuring data availability
Key Data Points to Capture:
// From convert.currentData
var experienceId = "100127238"; // Key in experiences object
var variationId = experience.variation.id; // e.g., "1001186427"
var variationName = experience.variation.name;
var variationKey = experience.variation.key;
var isFirstTime = experience.firstTime;
// From convert.historicalData
var experienceId = "100127238"; // Key in experiences object
var variationId = experience.variationId; // or experience.variation_id
var variationName = experience.variationName; // or experience.variation_name
var goals = experience.goals; // Object with goal IDs as keys
REST API:
- Endpoint: https://data.convert.com/track/{PROJECT_ID}/{VISITOR_ID}?s={EVENTS}
- Event type: hitGoal
- Required data:
- expId: Experience/Experiment ID
- varId: Variation ID (from experience.variation.id or experience.variationId)
- goalId: Goal ID to trigger
Conclusion
With these two integration types, you can:
- Push experiment data from Convert.com to any analytics platform for unified reporting using the new experiences object structure
- Track backend conversions that occur outside the browser context using the REST API with proper experience and variation IDs
Both approaches use the same foundational data from Convert.com's JavaScript objects, ensuring consistent and accurate experiment tracking across your entire customer journey.
Key Takeaways:
- Use convert.currentData.experiences to access current page experiment data
- Use convert.historicalData.experiences to access all visitor experiment data across sessions
- Extract variation ID from experience.variation.id (currentData) or experience.variationId (historicalData)
- Always use _conv_q queue to ensure data is ready
- Store visitor ID and variation IDs for backend conversion tracking
- Send hitGoal events via REST API for server-side conversions
- Handle multiple experiments by looping through all experiences
For additional integration examples and support, visit the Convert.com Help Center.