API v2.0

Welcome to the apoorv developer hub. You'll find comprehensive guides and documentation to help you start working with apoorv as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started    
Suggest Edits

Introduction to VWO REST API

 

About the Document

This document will help you understand the basics of VWO APIs. VWO API is organized around REST and encodes data in JSON. Understanding VWO API will allow developers to create and manage VWO accounts, campaigns and variations.

Target Audience

This document assumes technical proficiency. If you wish to develop a new app or plugin for a new target, or have any questions, reach out to us at api@vwo.com.

Suggest Edits

Request Types

 

Request Types

The most commonly-used HTTP methods are POST, GET, PATCH, and DELETE that correspond to create, read, update, and delete (or CRUD) operations. You can add the following endpoints after the version in the API URL.

Method
Description
Result

GET

Used to retrieve an entity or list of entities. GET requests are always read-only. To retrieve a single entity, use its id in the URL. To retrieve multiple entities, leave it blank.

Upon successful execution, GET method returns the data in the body and a 200 OK code.

POST

Used to create an entity in VWO. For example, a variation in a campaign.
POST requests have a JSON encoded body and the Content-Type: application/json header.

Upon successful execution, POST method returns the created entity as JSON in the body, including a new id argument, and a 201 CREATED code.

PATCH

Used to update an entity in VWO. The URL includes the id of the entity to update.

Upon successful execution, PATCH method returns a 200 OK code and the data in the body.

DELETE

Used to remove an entity in VWO. The URL includes the id of the entity to delete. No data is sent in the body.

The response includes a 204 NO CONTENT code.

Suggest Edits

Response Codes

 

Response

Upon successful request, the response includes data and 200 OK (GET), 201 CREATED (POST), 200 OK (PATCH), or 204 NO CONTENT (DELETE) as the HTTP code. If the request fails, the response is one of the following error codes:

Response
What triggers the response?

400
(Bad Request)

If the request is not sent in valid JSON. Specify a Content-Type: application/json header in your request. If you sent valid JSON, the error may also mean specific fields that were invalid.

401
(Unauthorized)

If your API token was missing or included in the body rather than the header.

403
(Forbidden)

If you provided an API token but it was invalid or revoked, or if you don't have read/write access to the entity you're trying to view/edit.

404
(Not Found)

If the id used in the request was inaccurate or you don't have permission to view/edit it.

429
(Too Many Requests)

If you hit a rate limit for the API. If you receive this response, we recommend waiting at least 60 seconds before re-attempting the request.

503
(Service Unavailable)

If the API is overloaded or down for maintenance. If you receive this response, we recommend waiting at least 60 seconds before re-attempting the request.

Suggest Edits

API Rate Limits

 

We rate limit 1 request per second for every token. Applications are not rate limited, though the limit is applied upon the token generated for an account. If the application users/VWO users intend to use the API beyond the rate limits mentioned, then please drop us a mail at api@vwo.com with your requirement details.

Suggest Edits

Authentication and Authorization

 

VWO's API lets you interact with a user’s VWO account and allows you to act on your user's behalf to perform multiple operations. To do so, your application first needs to request authorization from users.

Each API request is authenticated by a token in the request header. If you provide a wrong token, or include a token in the request body rather than the header, the response will be an Authentication Failed error.

IMPORTANT
A user authentication token authorized to your application is not time-bound and is valid indefinitely without requiring you to re-authorize. You can revoke the token from its Control Panel.

Suggest Edits

Authentication for personal use of API

 

Authentication for Personal Use of API

Please visit app.vwo.com/#/developers/tokens to generate an API token and use the token as part of every API request's header.

Suggest Edits

Authentication for third-party applications

 

Authentication for Third-Party Applications

For Third Party Applications, create an application via our Developers Dashboard
http://app.vwo.com/#/developers/applications
After creating the application, redirect the user to the following Authorization URL(shared below).

Path Syntax:
http://app.vwo.com/#/authorize/:applicationId

Example:
http://app.vwo.com/#/authorize/123456

*where the Application getting authorized has the applicationId as 123456

Authorization URL redirects the user to VWO, where an interface allows the user to authorize an application. The interface allows the user to choose the account for which the application will get the required access. On successful authorization, the user is redirected back to the application (if the redirect url has been specified) along with the authentication token as part of the query parameters. Although, if the redirect url has not been specified in the application settings, then, upon successful authorization, the user sees the authentication token for use in the application which initiated the authorization.

The authentication token can then be used with every API call to perform all operations available via API.

Draft exposes its data through a REST API using JSON serialization and protected with OAuth 2. Using API, you can fetch all or specific draft, update or delete an existing test in VWO.

Suggest Edits

Get all drafts campaigns

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/drafts
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/drafts
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/drafts' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/drafts")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/drafts");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/drafts"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": [
    {
      "draftId": 14597,
      "type": "ab",
      "status": "draft",
      "platform": "website",
      "createdOn": 1412649106,
      "currentDraftStepIndex": 2,
      "name": "Campaign 142",
      "urls": [
        {
          "value": "http:\/\/wingify.com"
        }
      ],
      "createdBy": {
        "id": 1,
        "name": "Backend Testing"
      }
    }
  ]
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

 

Get Current / Sub Account Drafts.

Request URI for Sub Account

GET /accounts/1/drafts
Suggest Edits

Get specific draft campaign

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/drafts/draft_id
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/drafts/draft_id
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/drafts/draft_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/drafts/draft_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/drafts/draft_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/drafts/draft_id"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "draftId": 14597,
    "createdBy": 1,
    "platform": "website",
    "isAdvancedMode": false,
    "currentDraftStepIndex": 2,
    "type": "ab",
    "urls": [
      {
        "type": "url",
        "value": "http:\/\/wingify.com"
      }
    ],
    "primaryUrl": "http:\/\/wingify.com",
    "globalSegment": {
      "segmentationType": "pre",
      "platform": "website",
      "id": "1",
      "type": "predefined",
      "name": "Direct",
      "description": "Segment to allow only direct traffic"
    },
    "variations": [
      {
        "platform": "website",
        "id": 1,
        "name": "Control",
        "editorData": {
          "stack": []
        },
        "deployContent": []
      },
      {
        "platform": "website",
        "id": 2,
        "name": "Variation 1",
        "editorData": {
          "stack": [
            {
              "el": 0,
              "op": {
                "opName": "html",
                "html": "The company  pioneered easy A\/B testing"
              },
              "depending": false,
              "XPath": "BODY > NOSCRIPT:first-child + SCRIPT + HEADER#top_header + SECTION > DIV:first-child > DIV:first-child > H2:first-child",
              "parentTag": "DIV"
            }
          ]
        },
        "deployContent": [
          {
            "jsString": "var ctx=vwo_$(x);ctx.html(\"The company  pioneered easy A\/B testing\");",
            "cssSelector": "HEADER#top_header + SECTION > DIV:first-child > DIV:first-child > H2:first-child"
          }
        ]
      }
    ],
    "status": "draft",
    "goals": [
      {
        "id": 1,
        "name": "Goal 1",
        "type": "visitPage",
        "isPrimary": true,
        "urls": [
          {
            "type": "url",
            "value": "http:\/\/wingify.com"
          }
        ],
        "cssSelectors": []
      }
    ],
    "name": "Campaign 142",
    "newCampaignName": "Campaign 142",
    "percentTraffic": 100,
    "isHeatmapEnabled": true
  }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

draft_id
int32
required

Draft Id

 

Get specific draft of Current / Sub Account.

Request URI for Sub Account

GET /accounts/1/drafts/14597
Suggest Edits

Update draft campaigns

 

Header Auth

 Authentication is required for this endpoint.
patchhttps://app.vwo.com/api/v2/accounts/account_id/drafts/draft_id
curl --request PATCH \
  --url https://app.vwo.com/api/v2/accounts/current/drafts/draft_id
var request = require("request");

var options = { method: 'PATCH',
  url: 'https://app.vwo.com/api/v2/accounts/current/drafts/draft_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/drafts/draft_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PATCH", "https://app.vwo.com/api/v2/accounts/current/drafts/draft_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/drafts/draft_id"

response = requests.request("PATCH", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "draftId": 14597,
    "createdOn": 1416225457,
    "createdBy": {
      "id": 1,
      "name": "Backend Testing"
    }
  }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

draft_id
int32
required

Draft Id

 

Request Format

{
  "draftId": 14597,
  "createdBy": 1,
  "platform": "website",
  "isAdvancedMode": false,
  "currentDraftStepIndex": 3,
  "type": "ab",
  "urls": [
    {
      "type": "url",
      "value": "http:\/\/wingify.com"
    }
  ],
  "primaryUrl": "http:\/\/wingify.com",
  "globalSegment": {
    "segmentationType": "pre",
    "platform": "website",
    "id": "1",
    "type": "predefined",
    "name": "Direct",
    "description": "Segment to allow only direct traffic"
  },
  "variations": [
    {
      "platform": "website",
      "id": 1,
      "name": "Control",
      "editorData": {
        "stack": []
      },
      "deployContent": [],
      "segmentEligibility": "ALL",
      "segment": {
        "type": "custom",
        "eligibility": "ALL"
      },
      "percentSplit": 50
    },
    {
      "platform": "website",
      "id": 2,
      "name": "Variation 1",
      "editorData": {
        "stack": [
          {
            "el": 0,
            "op": {
              "opName": "html",
              "html": "The company  pioneered easy A\/B testing"
            },
            "depending": false,
            "XPath": "BODY > NOSCRIPT:first-child + SCRIPT + HEADER#top_header + SECTION > DIV:first-child > DIV:first-child > H2:first-child",
            "parentTag": "DIV"
          }
        ]
      },
      "deployContent": [
        {
          "jsString": "var ctx=vwo_$(x);ctx.html(\"The company  pioneered easy A\/B testing\");",
          "cssSelector": "HEADER#top_header + SECTION > DIV:first-child > DIV:first-child > H2:first-child"
        }
      ],
      "segmentEligibility": "ALL",
      "segment": {
        "type": "custom",
        "eligibility": "ALL"
      },
      "percentSplit": 50
    }
  ],
  "status": "draft",
  "goals": [
    {
      "id": 1,
      "name": "Goal 1",
      "type": "visitPage",
      "isPrimary": true,
      "urls": [
        {
          "type": "url",
          "value": "http:\/\/wingify.com"
        }
      ],
      "cssSelectors": []
    }
  ],
  "name": "test Campaign",
  "newCampaignName": "Campaign 142",
  "percentTraffic": 100,
  "isHeatmapEnabled": true,
  "numVariationsWithEligibilitySeg": 0,
  "isCustomSplitEnabled": false,
  "integrations": {
    "ga": {
      "enabled": false,
      "slot": 4,
      "prefix": ""
    },
    "clicktale": {
      "enabled": false
    },
    "ua": {
      "enabled": false,
      "dimension": 1,
      "prefix": ""
    },
    "gtm": {
      "enabled": false
    },
    "isGaPremium": false
  },
  "isPostSegmentationEnabled": false
}

Update draft of Current / Sub Account.

Request URI for Sub Account

PATCH /accounts/1/drafts/14597
Suggest Edits

Delete draft campaigns

 

Header Auth

 Authentication is required for this endpoint.
deletehttps://app.vwo.com/api/v2/accounts/account_id/drafts/draft_id
curl --request DELETE \
  --url https://app.vwo.com/api/v2/accounts/current/drafts/draft_id
var request = require("request");

var options = { method: 'DELETE',
  url: 'https://app.vwo.com/api/v2/accounts/current/drafts/draft_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/drafts/draft_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Delete.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "https://app.vwo.com/api/v2/accounts/current/drafts/draft_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/drafts/draft_id"

response = requests.request("DELETE", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

draft_id
int32
required

Draft Id

 

Delete draft of Current / Sub Account.

Request URI for Sub Account

DELETE /accounts/1/drafts/14597
Suggest Edits

Campaigns

 

Developers can programmatically access test resources, get details of a test, create, update, and share links of your campaigns.

Suggest Edits

Campaign resource representation

 
Property
Type
Description
Editable

id

integer

Campaign Id

No

name

string

Campaign Name

Yes

type

string

Campaign type

Valid values include ab, multivariate, heatmap, conversion, split

Yes

status

string

Campaign status

Yes

createdOn

timestamp

Campaign creation time

No

labels

Nested Object

See CampaignLabel resource

Yes

percentTraffic

float

Percentage traffic allocated to the campaign

Yes

isCrossDomainEnabled

boolean

Tracking conversions across multiple domains

Yes

createdBy

NestedObject

Contains the information of user who created the campaign

createdBy.id

integer

User Id

No

createdBy.name

string

User name

No

createdBy.imageUrl

link

User gravatar link

No

urls

Nested Object

Urls to be included in the campaign

Yes

urls.{index}.type

String

Url type

Valid values include url,startsWith, endsWith,contains,pattern,regex

Yes

urls.{index}.value

Link

Url value

Yes

excludedUrls

Nested Object

Urls to be excluded in the campaign

Yes

excludedUrls.{index}.type

String

Url type

Yes

excludedUrls.{index}.value

Link

Url value

Yes

primaryUrl

link

Url on which test needs to be created

Yes

integrations

Nested Object

See integration resource for more details

Yes

thresholds

Nested Object

Thresholds for campaign data collection

thresholds.winningPercent

Float

Threshold for winning variation

Yes

thresholds.losingPercent

Float

Threshold for losing variation

Yes

thresholds.visitors

integer

Threshold for number of visitors

Yes

device

string

Device for which the campaign was created

No

variations

Nested Object

See variation resource for details

Yes

sections

Nested Object

See section resource for details

Yes

goals

Nested Object

See goal resource for details

Yes

dataIntervalRange

Nested Object

Date Range for collected campaign range

dataIntervalRange.intervalSize

timestamp

Size of intervals for which data is shown

No

dataIntervalRange.startTime

timestamp

Campaign data start time which is selected

No

dataIntervalRange.endTime

timestamp

Campaign data end time which is selected

No

dataIntervalRange.limitingStartTime

timestamp

Campaign data start time for which overall data is collected

No

dataIntervalRange.limitingEndTime

timestamp

Campaign data end time for which overall data is collected

No

variationGoalData

Nested Object

Campaign data for each variation-goal combination

No

variationGoalData.variation

integer

Variation Id

No

variationGoalData.goal

integer

Goal Id

No

variationGoalData.aggregated

Nested Object

Aggregated data for variation-goal combination

No

variationGoalData.aggregated.visitorCount

integer

visitor count

No

variationGoalData.aggregated.conversionCount

integer

conversion count

No

variationGoalData.aggregated.conversionRate

float

conversion rate

No

variationGoalData.aggregated.standardError

float

standard error

No

variationGoalData.aggregated.totalRevenue

integer

total revenue if revenue type goal is selected

No

variationGoalData.aggregated.revenuePerVisitor

float

revenue per visitor

No

variationGoalData.aggregated.revenuePerConversion

float

revenue per conversion

No

variationGoalData.aggregated.revenuePerVisitorStandardError

float

revenue per visitor standard error

No

variationGoalData.aggregated.revenuePerConversionStandardError

float

revenue per conversion standard error

No

variationGoalData.isLoser

boolean

if variation-goal combination is loser

No

variationGoalData.isWinner

boolean

if variation-goal combination is winner

No

variationGoalData.intervalWise

Nested Object

Interval wise data for variation-goal combination

No

variationGoalData.intervalWise.{index}.interval

timestamp

interval time

No

variationGoalData.intervalWise.{index}.visitorCount

integer

visitor count

No

variationGoalData.intervalWise.{index}.conversionCount

integer

conversion count

No

variationGoalData.intervalWise.{index}.totalCount

integer

total count

No

stats.conversionRate

integer

Conversion rate for the campaign (Default :0.05)

Yes

stats.certaintyMode

integer

Certainty Modes
High Certainty: 0.01
Balanced Mode: 0.075
Quick Learnings: 0.20

(Default : 0.01)

Yes

stats.expectedMonthlyVisitors

integer

Monthly expected Visitors on the website whose campaign is created (Default : 300000)

Yes

stats.expectedRevenuePerVisitor

integer

Expected Revenue per visitor (Default : 2)

Yes

stats.liftInConversionRate

integer

Expected lift in Improvement Rate to be achieved by this campaign
(Default : 0.05)

Yes

Suggest Edits

Get all campaigns in an account / sub-account

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/campaigns
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/campaigns");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": {
        [{
            "id": 7,
            "name": "Campaign 35",
            "type": "ab",
            "platform": "website",
            "status": "NOT_STARTED",
            "createdOn": 1417421529,
            "isDeleted": false,
            "createdBy": {
                "id": 44349,
                "name": "Sample",
                "imageUrl": "//gravatar.com/avatar/f4fedd3b67d066bfcce237a11da14825?s=24&d=https%3A%2F%2Fapp.vwo.com%2Fassets%2Fimages%2Favatar-new.png"
            },
            "primaryUrl": "http://wingify.com",
            "urls": [{
                "type": "url",
                "value": "http://wingify.com"
            }],
            "labels": [],
            "goals": {
                "partialCollection": [{
                    "id": 2,
                    "isPrimary": true,
                    "name": "New name",
                    "type": "visitPage",
                    "averageData": []
                }],
                "offset": 0,
                "totalCount": 3
            },
            "primaryGoal": 2,
            "variations": {
                "partialCollection": [],
                "totalCount": 3
            }
        }]
    }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

Query Params

limit
int32

Limit the number of campaigns to be returned

offset
string

Offset where campaign should be fetched from

 

Get the campaigns of an account

Note:

Data will be returned wrapped in the partialCollection along with count of total campaigns if the campaign count exceed the limit.

Request URI for Sub Account

GET /accounts/40505/campaigns
Suggest Edits

Get details of a specific campaign

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "id": 7,
    "name": "Campaign 7",
    "type": "ab",
    "status": "NOT_STARTED",
    "createdOn": 1472036883,
    "labels": [],
    "percentTraffic": 100,
    "createdBy": {
      "id": 40505,
      "name": "Sample",
      "imageUrl": "*****"
    },
    "urls": [
      {
        "type": "url",
        "value": "http://wingify.com"
      }
    ],
    "excludedUrls": [],
    "primaryUrl": "http://wingify.com",
    "integrations": {
      "ga": {
        "enabled": false,
        "slot": 4,
        "prefix": ""
      },
      "clicktale": {
        "enabled": false
      },
      "ua": {
        "enabled": false,
        "dimension": 1,
        "prefix": ""
      },
      "gtm": {
        "enabled": false
      }
    },
    "thresholds": {
      "winningPercent": 0.95,
      "losingPercent": 0.05,
      "visitors": 20
    },
    "device": "desktop",
    "variations": [
      {
        "id": 1,
        "name": "Control",
        "isControl": true,
        "isDisabled": false,
        "heatmapThumbUrl": "//heatmap.visualwebsiteoptimizer.com/h/viswebopt-1_256_1_calc-0.png",
        "screenshots": {
          "quick": "//s3.amazonaws.com/wfyss.visualwebsiteoptimizer.com/1/256_1_c9dd0f600be0b9fc8490bcd85ae0f95d.png"
        },
        "percentSplit": 100,
        "editorData": {
          "stack": null
        },
        "isBase": true
      }
    ],
    "goals": [
      {
        "id": 1,
        "isPrimary": true,
        "name": "New goal",
        "excludedUrls": [],
        "isCreatedInEditor": false,
        "type": "visitPage",
        "urls": [
          {
            "type": "url",
            "value": "http://wingify.com"
          }
        ],
        "averageData": []
      }
    ],
    "dataIntervalRange": [],
    "variationGoalData": [],
    "schedules": [],
    "isCrossDomainEnabled": false,
    "stats": {
      "conversionRate": "0.05",
      "liftInConversionRate": "0.05",
      "certaintyMode": "0.01",
      "expectedMonthlyVisitors": 300000,
      "expectedRevenuePerVisitor": "2"
    }
  }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

 

Get details of a specific campaign

Request URI for Sub Account

GET /accounts/40505/campaigns/7
Suggest Edits

Create a campaign

 

Header Auth

 Authentication is required for this endpoint.
posthttps://app.vwo.com/api/v2/accounts/account_id/campaigns
curl --request POST \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns
var request = require("request");

var options = { method: 'POST',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://app.vwo.com/api/v2/accounts/current/campaigns");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": {
        "id": 15,
        "status": "NOT_STARTED",
        "goals": [
            {
                "id": 1,
                "name": "New goal"
            }
        ]
    }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

 

Request Format

{
  "type" : "ab",
  "urls": [
            {
                "type": "url",
                "value": "http://wingify.com"
            }
        ],
  "primaryUrl" : "http://wingify.com",
  "goals":[{  
      "name":"New goal",
      "type":"visitPage",
      "urls":[  
         {  
            "type":"url",
            "value":"http://wingify.com"
         }
      ]
   }],
  "stats" : {
   	  "conversionRate" : 0.05,
      "certaintyMode" : 0.01,
      "expectedMonthlyVisitors" : 300000,
      "expectedRevenuePerVisitor" : 2,
      "liftInConversionRate" : 0.05
  }
}

Create a campaign

Note:

If stats are not provided, default value for stats (same as given in this request) are used for the campaign created.

Note:

For split campaign creation, two or more variations must be present in the request with urls for which the split campaign needs to be run.

Request URI for Sub Account

POST /accounts/40505/campaigns
Suggest Edits

Update a campaign

 

Header Auth

 Authentication is required for this endpoint.
patchhttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id
curl --request PATCH \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id
var request = require("request");

var options = { method: 'PATCH',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PATCH", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id"

response = requests.request("PATCH", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "id": 15,
    "name": "New name",
    "type": "ab",
    "status": "NOT_STARTED",
    "createdOn": 1472631589,
    "labels": [],
    "percentTraffic": 100,
    "createdBy": {
      "id": 40505,
      "name": "Sample",
      "imageUrl": "*****"
    },
    "urls": [
      {
        "type": "url",
        "value": "http://wingify.com"
      }
    ],
    "excludedUrls": [],
    "primaryUrl": "http://wingify.com",
    "integrations": {
      "ga": {
        "enabled": false,
        "slot": 4,
        "prefix": ""
      },
      "clicktale": {
        "enabled": false
      },
      "ua": {
        "enabled": false,
        "dimension": 1,
        "prefix": ""
      },
      "gtm": {
        "enabled": false
      }
    },
    "thresholds": {
      "winningPercent": 0.95,
      "losingPercent": 0.05,
      "visitors": 20
    },
    "device": "desktop",
    "variations": [
      {
        "id": 1,
        "name": "Control",
        "isControl": true,
        "isDisabled": false,
        "heatmapThumbUrl": "//heatmap.visualwebsiteoptimizer.com/h/viswebopt-1_257_1_calc-0.png",
        "screenshots": {
          "quick": "//s3.amazonaws.com/wfyss.visualwebsiteoptimizer.com/1/257_1_c9dd0f600be0b9fc8490bcd85ae0f95d.png"
        },
        "percentSplit": 100,
        "editorData": {
          "stack": null
        },
        "isBase": true
      }
    ],
    "goals": [
      {
        "id": 1,
        "isPrimary": true,
        "name": "New goal",
        "excludedUrls": [],
        "isCreatedInEditor": false,
        "type": "visitPage",
        "urls": [
          {
            "type": "url",
            "value": "http://wingify.com"
          }
        ],
        "averageData": []
      }
    ],
    "dataIntervalRange": [],
    "variationGoalData": [],
    "schedules": [],
    "stats": {
      "conversionRate": "0.05",
      "liftInConversionRate": "0.05",
      "certaintyMode": "0.01",
      "expectedMonthlyVisitors": 300000,
      "expectedRevenuePerVisitor": "2"
    }
  }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

 

Request Format

{
  "campaigns" : {
  		"name" : "New name"
  }
}

Update a campaign

Request URI for Sub Account

PATCH /accounts/40505/campaigns/15
Suggest Edits

Update campaign status

 

Header Auth

 Authentication is required for this endpoint.
patchhttps://app.vwo.com/api/v2/accounts/account_id/campaigns/status
curl --request PATCH \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/status
var request = require("request");

var options = { method: 'PATCH',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/status' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/status")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PATCH", "https://app.vwo.com/api/v2/accounts/current/campaigns/status");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/status"

response = requests.request("PATCH", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": {
        "status": "STOPPED",
        "ids": [
            14,
            15
        ]
    }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

 

Request Format

{
  "ids" : [14, 15],
  "status" : "TRASHED"
}

Update campaign status

Note:

Valid status changes include TRASHED, RESTORED, RUNNING, STOPPED, PAUSED

Request URI for Sub Account

PATCH /accounts/40505/campaigns/status
Suggest Edits

Goal resource representation

 
Property
Type
Description
Editable

id

Int

Goal Id

No

type

string

Goal Type

Valid values include visitPage, engagement, formSubmit, clickLink, clickElement, revenue, custom-conversion

Note:Please take caution while changing type, it might impact the data collection

Yes

name

string

Goal Name

Yes

isPrimary

boolean

Flag which signifies if the goal is primary goal or not

No

urls

Nested Object

Contains the url related information on which goal will be triggered.

See Campaign resource for more details on this

Yes

cssSelectors

list

Goal path

cssSelector.0

string

selector path

Yes

isCreatedInEditor

boolean

Flag if the goal was created in editor or not

No

Note:

urls is not required for engagement type goal

Note:

Multiple cssSelectors should be added as array values, like ["selector1, selector2"]

Suggest Edits

Get all goals of a campaign

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/goals
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/goals
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/goals' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/goals")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/goals");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/goals"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": [
        {
            "id": 2,
            "isPrimary": true,
            "name": "Goal 2",
            "urls": [
                {
                    "type": "url",
                    "value": "http://wingify.com"
                }
            ],
            "excludedUrls": [],
            "cssSelectors": [
                null
            ],
            "isCreatedInEditor": false,
            "type": "visitPage"
        }
    ]
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

 

Get all the goals of a campaign

Request URI for Sub Account

GET /accounts/40505/campaigns/7/goals
Suggest Edits

Get details of a specific goal in a campaign

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/goals/goal_id
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/goals/goal_id
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/goals/goal_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/goals/goal_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/goals/goal_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/goals/goal_id"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": {
        "id": 2,
        "isPrimary": true,
        "name": "Goal 2",
        "urls": [
            {
                "type": "url",
                "value": "http://wingify.com"
            }
        ],
        "excludedUrls": [],
        "cssSelectors": [
            null
        ],
        "isCreatedInEditor": false,
        "type": "visitPage"
    }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

goal_id
int32
required

Goal Id

 

Get details of a specific goal in a campaign

Request URI for Sub Account

GET /accounts/40505/campaigns/7/goals/2
Suggest Edits

Create a campaign goal

 

Header Auth

 Authentication is required for this endpoint.
posthttps://app.vwo.com/api/v2/accounts/account_id/campaign/campaign_id/goals
curl --request POST \
  --url https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals
var request = require("request");

var options = { method: 'POST',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": {
        "id": 3,
        "isPrimary": false,
        "name": "New goal",
        "urls": [
            {
                "type": "url",
                "value": "http://wingify.com"
            }
        ],
        "excludedUrls": [],
        "cssSelectors": [
            null
        ],
        "isCreatedInEditor": false,
        "type": "visitPage"
    }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

 

Request URI for Sub Account

POST /accounts/40505/campaigns/7/goals

Request Format

{  
   "goals":{  
      "name":"New goal",
      "type":"visitPage",
      "urls":[  
         {  
            "type":"url",
            "value":"http://wingify.com"
         }
      ]
   }
}

Create a campaign goal

Note:

  • valid type includes visitPage, engagement, formSubmit, clickLink, clickElement, revenue, custom-conversion
  • name is a required property
  • for type clickElement, cssSelectors is required
  • for type visitPage, formSubmit, clickLink, revenue, custom-conversion, urls is required
  • valid url type includes url, startsWith, endsWith, contains, pattern, regex, cssSelector

-

Suggest Edits

Update a campaign goal

 

Header Auth

 Authentication is required for this endpoint.
patchhttps://app.vwo.com/api/v2/accounts/account_id/campaign/campaign_id/goals/goal_id
curl --request PATCH \
  --url https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals/goal_id
var request = require("request");

var options = { method: 'PATCH',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals/goal_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals/goal_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PATCH", "https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals/goal_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals/goal_id"

response = requests.request("PATCH", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": {
        "id": 2,
        "isPrimary": true,
        "name": "New name",
        "urls": [
            {
                "type": "url",
                "value": "http://wingify.com"
            }
        ],
        "excludedUrls": [],
        "cssSelectors": [
            null
        ],
        "isCreatedInEditor": false,
        "type": "visitPage"
    }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

goal_id
int32
required

Goal Id

 

Request URI for Sub Account

PATCH /accounts/40505/campaigns/7/goals/2

Request Format

{  
   "goals": {  
      "name":"New name"
   }
}

Update a campaign goal

Suggest Edits

Delete a campaign goal

 

Header Auth

 Authentication is required for this endpoint.
deletehttps://app.vwo.com/api/v2/accounts/account_id/campaign/campaign_id/goals/goal_id
curl --request DELETE \
  --url https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals/goal_id
var request = require("request");

var options = { method: 'DELETE',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals/goal_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals/goal_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Delete.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals/goal_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaign/campaign_id/goals/goal_id"

response = requests.request("DELETE", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

goal_id
int32
required

Goal Id

 

Delete a campaign goal

Request URI for Sub Account

DELETE /accounts/40505/campaigns/7/goals/2
Suggest Edits

Variations

 
Suggest Edits

Variation resource representation

 
Property
Type
Description
Editable

id

Int

Variation Id

Note: Please ensure that variation Id is serial. For eg, if you have variations with ids 1,2,3 and you delete variation id 2, now you would have the variation ids 1, 2; 3 would be updated to 2

No

name

string

Variation Name

Yes

isControl

boolean

Flag which signifies if the variation is control variation

No

isDisabled

boolean

Flag which signifies if the variation is disabled

Note: Please set the percentSplit to 0 for the given variation to disable it

No

percentSplit

float

Percentage Traffic allocated for variation

Yes

editorData

Nested Object

Contains the JS/CSS changes created for the variation

No

editorData.stack

list

stack contains the list of the changes for the variation

No

heatmapThumbUrl

link

Link for the heatmap thumbnail

No

screenshots

list

Contains the link of screenshots for the selected browsers for the variation

No

sectionId

int

Section Id

Note: This would be 1 except the MULTIVARIATE campaign. It would be meaningful in that case only.

No

Note:

For adding js/css changes in variations, please use changes property in request body. These changes will be override any previous changes, if any.

Note

Variation splitPercent will be equally distributed among all variations on the creation of a new variation, which can be updated via update request

Suggest Edits

Get all variations of a campaign

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/variations
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": [
        {
            "id": 1,
            "name": "Control",
            "isControl": true,
            "isDisabled": false,
            "heatmapThumbUrl": "//heatmap.visualwebsiteoptimizer.com/h/viswebopt-40505_7_1_calc-0.png",
            "screenshots": {
                "quick": "//s3.amazonaws.com/wfyss.visualwebsiteoptimizer.com/40505/7_1_8cf9ad535ba453c84abd4c38617f93b4.png"
            },
            "percentSplit": 50,
            "editorData": {
                "stack": []
            },
            "sectionId": 1
        }
    ]
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

 

Get all the variations of a campaign

Request URI for Sub Account

GET /accounts/40505/campaigns/7/variations
Suggest Edits

Get details of a specific campaign variation

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/variations/variation_id
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": {
        "id": 1,
        "name": "Control",
        "isControl": true,
        "isDisabled": false,
        "heatmapThumbUrl": "//heatmap.visualwebsiteoptimizer.com/h/viswebopt-40505_7_1_calc-0.png",
        "screenshots": {
            "quick": "//s3.amazonaws.com/wfyss.visualwebsiteoptimizer.com/40505/7_1_8cf9ad535ba453c84abd4c38617f93b4.png"
        },
        "percentSplit": 50,
        "editorData": {
            "stack": []
        },
        "sectionId": 1
    }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

variation_id
string
required

Use sectionId,variationId for the MULTIVARIATE campaign

 

Get details of a specific campaign variation

Request URI for Sub Account

GET /accounts/40505/campaigns/7/variations/1
Suggest Edits

Create a campaign variation

 

Header Auth

 Authentication is required for this endpoint.
posthttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/variations
curl --request POST \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations
var request = require("request");

var options = { method: 'POST',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": {
        "id": 3,
        "name": "New shiny variation",
        "isControl": false,
        "isDisabled": false,
        "heatmapThumbUrl": "//heatmap.visualwebsiteoptimizer.com/h/viswebopt-40505_7_3_calc-0.png",
        "screenshots": {
            "quick": "//s3.amazonaws.com/wfyss.visualwebsiteoptimizer.com/40505/7_3_8cf9ad535ba453c84abd4c38617f93b4.png"
        },
        "percentSplit": 33.3333,
        "editorData": {
            "stack": null
        }
    }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

 

Request Format

{
  "variations" : {
		"name": "New shiny variation"
  }
}

Create a campaign variation

Info:

To add changes to the variation, please add changes under the key 'changes'. For e.g. to show an alert in variation

{
"variations" : {
.
.
"changes" : "<script>alert('Hello World');</script>"
.
.
}
}

Request URI for Sub Account

POST /accounts/40505/campaigns/7/variations
Suggest Edits

Update a campaign variation

 

Header Auth

 Authentication is required for this endpoint.
patchhttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/variations/variation_id
curl --request PATCH \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id
var request = require("request");

var options = { method: 'PATCH',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PATCH", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id"

response = requests.request("PATCH", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": {
        "id": 1,
        "name": "New name",
        "isControl": true,
        "isDisabled": false,
        "heatmapThumbUrl": "//heatmap.visualwebsiteoptimizer.com/h/viswebopt-40505_7_1_calc-0.png",
        "screenshots": {
            "quick": "//s3.amazonaws.com/wfyss.visualwebsiteoptimizer.com/40505/7_1_8cf9ad535ba453c84abd4c38617f93b4.png"
        },
        "percentSplit": 50,
        "editorData": {
            "stack": []
        },
        "sectionId": 1
    }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

variation_id
string
required

Use sectionId,variationId for the MULTIVARIATE campaign

 

Request Format

{  
   "variations": {  
      "name":"New name"
   }
}

Update a campaign variation

Request URI for Sub Account

PATCH /accounts/40505/campaigns/7/variations/1
Suggest Edits

Delete a campaign variation

 

Header Auth

 Authentication is required for this endpoint.
deletehttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/variations/variation_id
curl --request DELETE \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id
var request = require("request");

var options = { method: 'DELETE',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Delete.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/variations/variation_id"

response = requests.request("DELETE", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

variation_id
string
required

Use sectionId,variationId for the MULTIVARIATE campaign

 

Delete a campaign variation

Note:

Please ensure that variation Id is serial. For example, if you have variations with ids 1,2,3 and you delete variation id 2, now you would have the variation ids 1, 2, whereas 3 would be updated to 2. So, issue a GET /variations after the delete which would return the updated variations.

Request URI for Sub Account

DELETE /accounts/40505/campaigns/7/variations/1
 
Suggest Edits

Section resource representation

 
Property
Type
Description
Editable

id

int

Section Id

No

name

string

Section Name

Yes

cssSelector

string

Section Path

No

variations

nested object

See variation resource

Note:

Only allowed for the MULTIVARIATE campaign

Suggest Edits

Get all sections of a campaign

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/sections
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": [
        {
            "id": 1,
            "name": "Baja Baja",
            "cssSelector": "DIV#js-header-fixed-trigger + SECTION > DIV:first-child > DIV:first-child > DIV:first-child",
            "variations": [
                {
                    "id": 1,
                    "name": "Control",
                    "isControl": true,
                    "isDisabled": false,
                    "heatmapThumbUrl": "//heatmap.visualwebsiteoptimizer.com/h/viswebopt-1_2905_1_calc-0.png",
                    "screenshots": {
                        "quick": "//s3.amazonaws.com/wfyss.visualwebsiteoptimizer.com/1/2905_1_c9dd0f600be0b9fc8490bcd85ae0f95d.png"
                    },
                    "editorData": {
                        "stack": []
                    }
                }
            ]
        }
    ]
}

Path Params

account_id
string
required

Use 'current' keyword to specify Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

 

Get all sections of a campaign

Request URI for Sub Account

GET /accounts/40505/campaigns/8/sections
Suggest Edits

Get details of a specific campaign section

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/sections/section_id
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": {
        "id": 1,
        "name": "Baja Baja",
        "cssSelector": "DIV#js-header-fixed-trigger + SECTION > DIV:first-child > DIV:first-child > DIV:first-child",
        "variations": [
            {
                "id": 1,
                "name": "Control",
                "isControl": true,
                "isDisabled": false,
                "heatmapThumbUrl": "//heatmap.visualwebsiteoptimizer.com/h/viswebopt-1_2905_1_calc-0.png",
                "screenshots": {
                    "quick": "//s3.amazonaws.com/wfyss.visualwebsiteoptimizer.com/1/2905_1_c9dd0f600be0b9fc8490bcd85ae0f95d.png"
                },
                "editorData": {
                    "stack": []
                }
            }
        ]
    }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

section_id
int32
required

Section Id

 

Get details of a specific campaign section

Request URI for Sub Account

GET /accounts/40505/campaigns/8/sections/1
Suggest Edits

Create a campaign section

 

Header Auth

 Authentication is required for this endpoint.
posthttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/sections
curl --request POST \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections
var request = require("request");

var options = { method: 'POST',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": [
        {
            "id": 2,
            "name": "New shiny section",
            "cssSelector": "DIV#js-header-fixed-trigger + SECTION > DIV:first-child > DIV:first-child > DIV:first-child",
            "variations": [
                {
                    "id": 1,
                    "name": "Control",
                    "isControl": true,
                    "isDisabled": false,
                    "heatmapThumbUrl": "//heatmap.visualwebsiteoptimizer.com/h/viswebopt-1_2905_1_calc-0.png",
                    "screenshots": {
                        "quick": "//s3.amazonaws.com/wfyss.visualwebsiteoptimizer.com/1/2905_1_c9dd0f600be0b9fc8490bcd85ae0f95d.png"
                    },
                    "editorData": {
                        "stack": []
                    }
                }
            ]
        }
    ]
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

 

Request Format

{
  "sections" : {
    "name": "New shiny section",
    "cssSelector": "DIV#js-header-fixed-trigger + SECTION > DIV:first-child > DIV:first-child > DIV:first-child",
    "variations" : [
      	{
      		"name" : "New shiny variation"
    	}
    ]
  }
}

Create a campaign section

Request URI for Sub Account

POST /accounts/40505/campaigns/8/sections
Suggest Edits

Update a campaign section

 

Header Auth

 Authentication is required for this endpoint.
patchhttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/sections/section_id
curl --request PATCH \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id
var request = require("request");

var options = { method: 'PATCH',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PATCH", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id"

response = requests.request("PATCH", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": {
        "id": 1,
        "name": "New name",
        "cssSelector": "DIV#js-header-fixed-trigger + SECTION > DIV:first-child > DIV:first-child > DIV:first-child",
        "variations": [
            {
                "id": 1,
                "name": "Control",
                "isControl": true,
                "isDisabled": false,
                "heatmapThumbUrl": "//heatmap.visualwebsiteoptimizer.com/h/viswebopt-1_2905_1_calc-0.png",
                "screenshots": {
                    "quick": "//s3.amazonaws.com/wfyss.visualwebsiteoptimizer.com/1/2905_1_c9dd0f600be0b9fc8490bcd85ae0f95d.png"
                },
                "editorData": {
                    "stack": []
                }
            }
        ]
    }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

section_id
int32
required

Section Id

 

Request Format

{
  "sections" : {
    "name" : "New name"
  }
}

Get details of a specific campaign section

Request URI for Sub Account

PATCH /accounts/40505/campaigns/8/sections/1
Suggest Edits

Delete a campaign section

 

Header Auth

 Authentication is required for this endpoint.
deletehttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/sections/section_id
curl --request DELETE \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id
var request = require("request");

var options = { method: 'DELETE',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Delete.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/sections/section_id"

response = requests.request("DELETE", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

section_id
int32
required

Section Id

 

Delete a campaign section

Request URI for Sub Account

DELETE /accounts/40505/campaigns/8/sections/2
 

You can manage your current account or sub-accounts via the following API Endpoints.
To understand accounts resource in depth, read our knowledge base article on VWO Accounts.

Suggest Edits

Retrieve all accounts

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts
import requests

url = "https://app.vwo.com/api/v2/accounts"

headers = {
    'token': "96ca71826128162811321nnjadsdjnsadkf33c4c03660a2398abd93f60c74ef1b442a434",
    'cache-control': "no-cache"
    }

response = requests.request("GET", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": [
    {
      "id": 916,
      "name": "New account",
      "createdOn": 1271158169,
      "enabled": true
    },
    {
      "id": 874,
      "name": "Test Account",
      "createdOn": 1269942600,
      "enabled": true
    }
  ]
}
 

Request URI

GET /accounts
Suggest Edits

Retrieve specific account

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "id": 1,
    "name": "Main Account",
    "createdOn": 1257680705,
    "timezone": "Asia\/Dhaka",
    "company": {
      "name": "",
      "website": "",
      "size": ""
    },
    "enabled": true
  }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

 

To retrieve information of a specific account, enter the associated campaign ID.

Request URI for Sub Account

GET /accounts/1
Suggest Edits

Create a sub-account

 

Header Auth

 Authentication is required for this endpoint.
posthttps://app.vwo.com/api/v2/accounts
curl --request POST \
  --url https://app.vwo.com/api/v2/accounts
var request = require("request");

var options = { method: 'POST', url: 'https://app.vwo.com/api/v2/accounts' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://app.vwo.com/api/v2/accounts");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "id": 40506,
    "name": "API Sub Account Name",
    "createdOn": 1415966384,
    "timezone": "GMT"
  }
}

Body Params

name
string
required

Sub-account name

 

Request URI

POST /accounts
Suggest Edits

Update account

 

Header Auth

 Authentication is required for this endpoint.
patchhttps://app.vwo.com/api/v2/accounts/account_id
curl --request PATCH \
  --url https://app.vwo.com/api/v2/accounts/account_id
var request = require("request");

var options = { method: 'PATCH',
  url: 'https://app.vwo.com/api/v2/accounts/account_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/account_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PATCH", "https://app.vwo.com/api/v2/accounts/account_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/account_id"

response = requests.request("PATCH", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "name": "API Account Name",
    "timezone": "Asia\/Kolkata",
    "enabled": true,
    "company": {
      "name": "API Company Name",
      "website": "http:\/\/wingify.com",
      "size": "1-200",
      "industry": {
        "type": "saas"
      }
    }
  }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

Body Params

name
string

Account Name

timezone
string

Timezone associated with the Account e.g. \"Asia\/Kolkata\"

enabled
boolean

Disable/Enable Account

company
object
 
company.name
string

Company name associated with the Account

company.website
string

Website URL of the Company, if any

company.size
string

Choose among these options ["1-200","201-500","501-1000","1001-2000","2000+"]

company.industry
object
 
company.industry.type
string

Industry Type of the Company

 

Update details of Account.

Category
Value to be passed in API

eCommerce / Internet Retail

ecommerce

Software / SaaS / Downloads

saas

Media / Publishers / Blog

media

Digital Marketing / Agency / Web Development Shop

agency

Travel and Tourism / Hotels / Hospitality

travel

Non-government / Charity

ngo

Entertainment

entertainment

Banking / Financial Services / Insurance

banking

Business Consulting

businessConsulting

Healthcare / Medicine / Bio

health

Education / Training

education

Telecom

telecom

Use enabled field to Enable/Disable account with Caution.

Request URI for Sub Account

PATCH /accounts/1

Request Format

{
  "name": "API Account Name",
  "timezone": "Asia\/Kolkata",
  "enabled": true,
  "company": {
    "name": "API Company Name",
    "website": "http:\/\/wingify.com",
    "size": "1-200",
    "industry": {
      "type": "saas"
    }
  }
}
Suggest Edits

Get all users

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/users
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/users
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/users' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/users")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/users");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/users"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": [
    {
      "id": 1,
      "name": "Backend Testing",
      "email": "dev+testing@wingify.com",
      "account": 1,
      "permission": "Admin",
      "createdOn": 1257680705,
      "phone": "FALSE",
      "country": "",
      "department": "",
      "title": ""
    },
    {
      "id": 951,
      "name": "Browse Only",
      "email": "browse-only@wingify.com",
      "permission": "Browse",
      "account": 1,
      "createdOn": 1271320843,
      "phone": "FALSE",
      "country": "",
      "department": "",
      "title": ""
    }
  ]
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

 

Get Current / Sub Account Users.

Request URI for Sub Account

GET /accounts/1/users
Suggest Edits

Get user details

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/users/user_id
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/users/user_id
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/users/user_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/users/user_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/users/user_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/users/user_id"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "id": 874,
    "name": "Test User",
    "email": "test-account@wingify.com",
    "createdOn": 1269942600,
    "permission": "Admin",
    "phone": "FALSE",
    "country": "",
    "department": "",
    "title": ""
  }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

user_id
int32
required

User Id

 

Get specific user of Current / Sub Account.

Request URI for Sub Account

GET /accounts/1/users/874
Suggest Edits

Create a user

 

Header Auth

 Authentication is required for this endpoint.
posthttps://app.vwo.com/api/v2/accounts/account_id/users
curl --request POST \
  --url https://app.vwo.com/api/v2/accounts/current/users
var request = require("request");

var options = { method: 'POST',
  url: 'https://app.vwo.com/api/v2/accounts/current/users' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/users")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://app.vwo.com/api/v2/accounts/current/users");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/users"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "id": 44350,
    "name": "Test via API",
    "email": "test+api@wingify.com",
    "createdOn": 1415876399,
    "permission": "Admin",
    "phone": "9999988877",
    "country": "India",
    "department": "Software Engineering",
    "title": "API Evangelist"
  }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

 

Create User in Current / Sub Account.

Request URI for Sub Account

POST /accounts/1/users
{
  "name": "Test via API",
  "email": "test+api@wingify.com",
  "password": "*password*",
  "confirmPassword": "*password*",
  "phone": "9999988877",
  "country": "India",
  "department": "Software Engineering",
  "title": "API Evangelist",
  "permission": "Admin"
}
Suggest Edits

Update user details

 

Header Auth

 Authentication is required for this endpoint.
patchhttps://app.vwo.com/api/v2/accounts/account_id/users/user_id
curl --request PATCH \
  --url https://app.vwo.com/api/v2/accounts/current/users/user_id
var request = require("request");

var options = { method: 'PATCH',
  url: 'https://app.vwo.com/api/v2/accounts/current/users/user_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/users/user_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PATCH", "https://app.vwo.com/api/v2/accounts/current/users/user_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/users/user_id"

response = requests.request("PATCH", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "id": 874,
    "name": "Test User",
    "email": "test-account@wingify.com",
    "createdOn": 1269942600,
    "permission": "Admin",
    "phone": "FALSE",
    "country": "",
    "department": "",
    "title": ""
  }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

user_id
int32
required

User Id

Body Params

name
string

Name of User

phone
string

Contact number of User

country
string

Country of User

department
string

Work department of User

title
string

Designation of User

permission
string

Select the permission of user among "Browse","Design","Publish","Admin"

 
{
  "name": "API User Name",
  "phone": "9999988877",
  "country": "India",
  "department": "Software Engineering",
  "title": "API Evangelist",
  "permission": "Browse"
}

Update specific user of Current / Sub Account.

Request URI for Sub Account

PATCH /accounts/1/users/874

Request Format

Suggest Edits

Delete users

 

Header Auth

 Authentication is required for this endpoint.
deletehttps://app.vwo.com/api/v2/accounts/account_id/users/user_id
curl --request DELETE \
  --url https://app.vwo.com/api/v2/accounts/current/users/user_id
var request = require("request");

var options = { method: 'DELETE',
  url: 'https://app.vwo.com/api/v2/accounts/current/users/user_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/users/user_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Delete.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "https://app.vwo.com/api/v2/accounts/current/users/user_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/users/user_id"

response = requests.request("DELETE", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

user_id
int32
required

User Id

 

DELETE specific user of Current / Sub Account.

Request URI for Sub Account

DELETE /accounts/1/users/874
Suggest Edits

Tracking Code

 

The VWO smart code snippet that you add to your pages contacts VWO server whenever a visitor lands on a test page. The server sends its response in two parts - static JavaScript code for running the test and dynamic test-specific data. Both the static and dynamic parts of the response are cached heavily at the server back-end, thereby minimizing the response time. With code minification and gzipping, the size of response decreases even further.

To understand more about VWO smart code, read our knowledge base article on VWO Accounts.

Suggest Edits

Get Smart Code of accounts

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/tracking-code
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/tracking-code
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/tracking-code' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/tracking-code")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/tracking-code");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/tracking-code"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": {
        "sync": "<!-- Start Visual Website Optimizer Synchronous Code -->\n<script type='text/javascript'>\nvar _vis_opt_account_id = 874;\nvar _vis_opt_protocol = (('https:' == document.location.protocol) ? 'https://' : 'http://');\ndocument.write('<s' + 'cript src=\"' + _vis_opt_protocol +\n'dev.visualwebsiteoptimizer.com/deploy/js_visitor_settings.php?v=1&a='+_vis_opt_account_id+'&url='\n+encodeURIComponent(document.URL)+'&random='+Math.random()+'\" type=\"text/javascript\">' + '<\\/s' + 'cript>');\n</script>\n\n<script type='text/javascript'>\nif(typeof(_vis_opt_settings_loaded) == \"boolean\") { document.write('<s' + 'cript src=\"' + _vis_opt_protocol +\n'd5phz18u4wuww.cloudfront.net/vis_opt.js\" type=\"text/javascript\">' + '<\\/s' + 'cript>'); }\n// if your site already has jQuery 1.4.2, replace vis_opt.js with vis_opt_no_jquery.js above\n</script>\n\n<script type='text/javascript'>\nif(typeof(_vis_opt_settings_loaded) == \"boolean\" && typeof(_vis_opt_top_initialize) == \"function\") {\n        _vis_opt_top_initialize(); vwo_$(document).ready(function() { _vis_opt_bottom_initialize(); });\n}\n</script>\n<!-- End Visual Website Optimizer Synchronous Code -->",
        "async": "<!-- Start Visual Website Optimizer Asynchronous Code -->\n<script type='text/javascript'>\nvar _vwo_code=(function(){\nvar account_id=874,\nsettings_tolerance=2000,\nlibrary_tolerance=2500,\nuse_existing_jquery=false,\n// DO NOT EDIT BELOW THIS LINE\nf=false,d=document;return{use_existing_jquery:function(){return use_existing_jquery;},library_tolerance:function(){return library_tolerance;},finish:function(){if(!f){f=true;var a=d.getElementById('_vis_opt_path_hides');if(a)a.parentNode.removeChild(a);}},finished:function(){return f;},load:function(a){var b=d.createElement('script');b.src=a;b.type='text/javascript';b.innerText;b.onerror=function(){_vwo_code.finish();};d.getElementsByTagName('head')[0].appendChild(b);},init:function(){settings_timer=setTimeout('_vwo_code.finish()',settings_tolerance);this.load('//dev.visualwebsiteoptimizer.com/j.php?a='+account_id+'&u='+encodeURIComponent(d.URL)+'&r='+Math.random());var a=d.createElement('style'),b='body{opacity:0 !important;filter:alpha(opacity=0) !important;background:none !important;}',h=d.getElementsByTagName('head')[0];a.setAttribute('id','_vis_opt_path_hides');a.setAttribute('type','text/css');if(a.styleSheet)a.styleSheet.cssText=b;else a.appendChild(d.createTextNode(b));h.appendChild(a);return settings_timer;}};}());_vwo_settings_timer=_vwo_code.init();\n</script>\n<!-- End Visual Website Optimizer Asynchronous Code -->"
    }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

 

Get Synchronous/Asynchronous Tracking Code for Current / Sub Account

Request URI for Sub Account

GET /accounts/874/tracking-code
Suggest Edits

Account Thresholds

 

Account threshold values indicate the level of confidence you can have on a variation to perform better as compared to the control (original) version of a website. VWO determines a winning variation in a campaign by calculating the Chance to beat original (CTBO) metric. The level of confidence in a variation is indicated by a value between 0%-100 percent.

You can set the threshold for winning variation, losing variation, and minimum visitors required to calculate which variation wins or loses.

Suggest Edits

Get account thresholds

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/thresholds
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/thresholds
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/thresholds' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/thresholds")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/thresholds");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/thresholds"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "winningPercent": 95,
    "losingPercent": 5,
    "visitors": 20
  }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

 

Get threshold for current and sub-accounts.

Request URI for Sub Account

GET /accounts/1/thresholds
Suggest Edits

Update account thresholds

 

Header Auth

 Authentication is required for this endpoint.
patchhttps://app.vwo.com/api/v2/accounts/account_id/thresholds
curl --request PATCH \
  --url https://app.vwo.com/api/v2/accounts/account_id/thresholds
var request = require("request");

var options = { method: 'PATCH',
  url: 'https://app.vwo.com/api/v2/accounts/account_id/thresholds' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/account_id/thresholds")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PATCH", "https://app.vwo.com/api/v2/accounts/account_id/thresholds");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/account_id/thresholds"

response = requests.request("PATCH", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "winningPercent": 95,
    "losingPercent": 5,
    "visitors": 21
  }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

Body Params

winningPercent
int32

Winning Percent

losingPercent
int32

Losing Percent

visitors
int32

Number of visitors

 

Update account Thresholds.

Request URI for Sub Account

PATCH /accounts/1/thresholds

Request Format:

{
  "winningPercent": 95,
  "losingPercent": 5,
  "visitors": 21
}
Suggest Edits

Third-party Integrations

 

Third-party integration allows you to integrate your VWO data with other analytics tools, providing a deeper insight into your campaign reports.

To understand third-party integration supported in VWO, read our knowledge base articles on VWO Integration.

Suggest Edits

Get integration settings of Current / Sub Account

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/integrations
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/account_id/integrations
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/account_id/integrations' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/account_id/integrations")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/account_id/integrations");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/account_id/integrations"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "ga": {
      "enabled": false,
      "slot": 4,
      "prefix": ""
    },
    "clicktale": {
      "enabled": false
    },
    "ua": {
      "enabled": false,
      "dimension": 1,
      "prefix": ""
    },
    "gtm": {
      "enabled": false
    },
    "isGaPremium": false
  }
}

Path Params

account_id
string
required

Account Id

 

Get Third Party Integrations for Current / Sub Account.

Request URI

GET /accounts/:account_id/integrations
Suggest Edits

Update integration settings for specific account

 

Header Auth

 Authentication is required for this endpoint.
patchhttps://app.vwo.com/api/v2/accounts/account_id/integrations
curl --request PATCH \
  --url https://app.vwo.com/api/v2/accounts/account_id/integrations
var request = require("request");

var options = { method: 'PATCH',
  url: 'https://app.vwo.com/api/v2/accounts/account_id/integrations' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/account_id/integrations")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PATCH", "https://app.vwo.com/api/v2/accounts/account_id/integrations");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/account_id/integrations"

response = requests.request("PATCH", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "ga": {
      "enabled": true,
      "slot": 4,
      "prefix": ""
    },
    "ua": {
      "enabled": false,
      "dimension": 1,
      "prefix": ""
    },
    "gtm": {
      "enabled": false
    },
    "clicktale": {
      "enabled": false
    },
    "isGaPremium": false
  }
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

Body Params

ga
object
 
ga.
array of mixed types

Information regarding Google Analytics

ga.enabled
boolean

Google Analytics whether enabled or not

ga.slot
int32

Google Analytics Slot

ga.prefix
string

Google Analytics Account prefix

ua
object
 
ua.
array of mixed types

Universal Analytics Settings

ua.enabled
string

Universal Analytics whether enabled or not

ua.dimension
string

Custom Dimension used inside Google Analytics

ua.prefix
string

Google Analytics Account prefix

gtm
object
 
gtm.
string

Settings for Google Tag Manager

gtm.enabled
boolean

Google Tag Manager whether enabled or not

clicktale
object
 
clicktale.
array of mixed types

ClickTale Settings

clicktale.enabled
boolean

Clicktale whether enabled or not

isGaPremium
boolean

Whether Google Analytics is premium

 

Update Third Party Integrations. Here's an example of the request params:

Request URI for Sub Account

PATCH /accounts/1/integrations

Request Format

{
  "ga": {
    "enabled": true,
    "slot": 4,
    "prefix": ""
  },
  "ua": {
    "enabled": false,
    "dimension": 1,
    "prefix": ""
  },
  "gtm": {
    "enabled": false
  },
  "clicktale": {
    "enabled": false
  },
  "isGaPremium": false
}
 
Suggest Edits

Get billing details of accounts

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/billing-details
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/billing-details
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/billing-details' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/billing-details")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/billing-details");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/billing-details"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "paymentProcessor": "2Checkout",
    "customerName": "",
    "billingAddress": "<br \/>",
    "changeBillingUrl": "https:\/\/www.2checkout.com\/va\/sales\/customer\/change_billing_method?sale_id=4491073920",
    "creditCardNumber": "-XXXX-XXXX-XX",
    "paymentMethod": "credit-card"
  }
}
 

Get Billing details for Account.

GET /accounts/billing-details
Suggest Edits

Get billing cycle details of accounts

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/billing-cycles
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/billing-cycles
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/billing-cycles' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/billing-cycles")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/billing-cycles");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/billing-cycles"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": [
    {
      "id": 1,
      "from": 1271924465,
      "to": 1275264000,
      "visitorsAllowed": 101000,
      "invoice": null,
      "plan": {
        "id": 1,
        "type": "FREE",
        "price": 0,
        "description": "Free account for existing beta users",
        "isEnterprise": false,
        "totalVisitors": 100000,
        "isUnlimitedPlan": false,
        "isTopVisitorPlan": false
      },
      "isCurrent": false,
      "visitorsUsed": 7,
      "usages": [
        {
          "account": 1,
          "visitorsUsed": 7
        },
        {
          "account": 874,
          "visitorsUsed": 0
        },
        {
          "account": 916,
          "visitorsUsed": 0
        },
        {
          "account": 1413,
          "visitorsUsed": 0
        },
        {
          "account": 2904,
          "visitorsUsed": 0
        }
      ]
    }
  ]
}
 

Get Billing Cycle details of Current Account.

GET /accounts/billing-cycles
Suggest Edits

Get account invoices

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/invoice
curl --request GET \
  --url 'https://app.vwo.com/api/v2/accounts/invoice?billing-cycle=billing-cycle'
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/invoice',
  qs: { 'billing-cycle': 'billing-cycle' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/invoice?billing-cycle=billing-cycle")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/invoice?billing-cycle=billing-cycle");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/invoice"

querystring = {"billing-cycle":"billing-cycle"}

response = requests.request("GET", url, params=querystring)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Query Params

billing-cycle
int32
required

Use the Billing Cycle Id

 

Returns PDF as response.

GET /accounts/invoice
Suggest Edits

Get labels

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/labels
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/labels
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/labels' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/labels")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/labels");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/labels"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": [
    {
      "id": 1,
      "name": "Demo"
    },
    {
      "id": 2,
      "name": "Real"
    },
    {
      "id": 3,
      "name": "Personal"
    }
  ]
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

 

Get labels for Current / Sub Accounts.

Request URI for Sub Account

GET /accounts/1/labels
Suggest Edits

Get labels of a specific campaign

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/labels
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": [
        {
            "id": 1,
            "name": "Demo"
        }
    ]
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

 

Request URL for Sub Account

GET /accounts/1/campaigns/72/labels

Get all the labels associated with a campaign

Suggest Edits

Add labels to a campaign

 

Header Auth

 Authentication is required for this endpoint.
posthttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/labels
curl --request POST \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels
var request = require("request");

var options = { method: 'POST',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "_data": [
        {
            "id": 1,
            "name": "Demo"
        },
        {
            "id": 2,
            "name": "Real"
        },
        {
            "id": 4,
            "name": "New shiny label"
        }
    ]
}

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

 

Request URI for Sub Account

POST /accounts/1/campaigns/72/labels

Request Format

{
    "labels": [
      {
        "name" : "New shiny label"
      }
    ]
}

Add labels to a campaign

Note: Mention id for associating existing account labels to campaign and name for creating a new label

Suggest Edits

Delete a campaign label

 

Header Auth

 Authentication is required for this endpoint.
deletehttps://app.vwo.com/api/v2/accounts/account_id/campaigns/campaign_id/labels/label_id
curl --request DELETE \
  --url https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels/label_id
var request = require("request");

var options = { method: 'DELETE',
  url: 'https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels/label_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels/label_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Delete.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels/label_id");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/current/campaigns/campaign_id/labels/label_id"

response = requests.request("DELETE", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

account_id
string
required

Use 'current' keyword to refer to the Main Account or the Integer Sub Account Id

campaign_id
int32
required

Campaign Id

label_id
int32
required

Label Id

 

Request URL for Sub Account

DELETE accounts/1/campaigns/72/labels/1

Delete a campaign label

Suggest Edits

Campaign labels

 

VWO Campaign labels are keywords or tags you associate with your campaigns. Adding a label helps you to easily identify campaigns and eliminates the need to browse the entire list when searching for a specific campaign.

 
Suggest Edits

Get partner details

 

Header Auth

 Authentication is required for this endpoint.
gethttps://app.vwo.com/api/v2/accounts/partners
curl --request GET \
  --url https://app.vwo.com/api/v2/accounts/partners
var request = require("request");

var options = { method: 'GET',
  url: 'https://app.vwo.com/api/v2/accounts/partners' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://app.vwo.com/api/v2/accounts/partners")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://app.vwo.com/api/v2/accounts/partners");

xhr.send(data);
import requests

url = "https://app.vwo.com/api/v2/accounts/partners"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "_data": {
    "freeUsers": 1,
    "paidUsers": 1,
    "sales": 49,
    "commissionPercent": "0.15",
    "totalCommission": 7.35,
    "commissionDisbursed": 12.35,
    "referralCode": "pc"
  }
}
 

Get partner details associated with an account.

GET /accounts/partners
Suggest Edits

Quick Start Guide

 

To create and run A/B tests, sign in to the VWO dashboard, and then select Mobile App A/B on the menu. If you are using the VWO A/B testing feature for the first time, click Start Mobile App A/B Testing to begin.

To create A/B tests for mobile apps:

Add the mobile app to be tested.

Define the variables you want to test.

Create A/B tests.

Adding the Mobile App to Test

Go to the Apps section on the page.

On the upper-right side of the screen, click Create App.
Type the name of the app you want to add, and then click Create.

As you add an app, VWO generates API keys for both the iOS and Android platforms. You can make a note of the API key under the Settings section and is used during app initialization.

Installing SDK

You can use CocoaPods to install the VWO iOS SDK. For CocoaPods installation, add pod 'VWO' to your Pod file.
Run the pod install command.

Click here for detailed installation instructions.

Initializing the SDK

After installing the SDK, you can initialize the app in the AppDelegate file by using the didFinishLaunchingWithOptions method.

Import VWO, and then call the launchForAPIKey method with your app key. Click here for detailed instructions.

// importing the VWO module
@import VWO;

// initialising the SDK
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [VWO launchForAPIKey:@"<your-api-key>" config: nil
     completion:^{
  		  //Code executed after launch is complete
	   } failure:^(NSString * _Nonnull error) {
		    // Failure handling
	}];
  return YES;
}
// importing the header file
import VWO

// initialising the SDK
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
VWO.launch(apiKey: "<your-api-key>", config: nil
  completion: {
	   //Code executed after launch is complete     
	}, failure: { error in
      print(error)
})
return true
}

Defining the Variables You Want to Test

Test variables are elements or parameters of your mobile app. After you define a variable, you can run an unlimited number of A/B tests on the variable, without doing any code changes or redeployment. For example, you can create a string-type variable for testing different text versions on the app screen.

Under the Apps tab, select the mobile app for which you want to create test variables.
To add an element for testing, under the Variables section, click Create Variable.
Assign a name to the variable, and then select its data type.
Type Default Value (current value or a value if there is no A/B test).
To add the variable, click Create. You can add multiple variables to an app.

You can view the relevant Java, Objective, or Swift code snippet in the right panel as you create the variable. You can use this code snippet to update the changes in your mobile app code.

int speed = [VWO intForKey:@"speed" defaultValue:5];
int speed = VWO.intFor(key: "speed", defaultValue: 5)

Create a Campaign

On the Mobile App A/B testing screen, go to the Campaigns tab, and then click Create.

Choose the App you want to test. All mobile apps you have added to VWO are listed here.

Select a platform where the app is running.

Enter a unique identifier in the Name of your test key field to filter your tests easily. The test key helps you execute the custom logic, as explained in this Code Blocks section.

Select Next, and then click Add Variable. All the variables you have created for the test are displayed here. You can choose to Create Variable by adding a new test variable.

Select the variable you want to test, and then enter the variation values. You can test multiple variables in one test. In the above example, we have added the speed variable, and then defined value as 20 for the variation. For control, the value is 10, which is the default value for the variable.

Based on the test key and variation names, VWO generates the code snippet that you can use in the mobile app.

To continue, click Next.

NSString *variationName = [VWO variationNameForTestKey:@"test_key"];
if ([variationName isEqualToString:@"Control"]) {
        // Code for Control
} else if ([variationName isEqualToString:@"Variation 1"]) {
        // Code for Variation 1
} else {

}
if let variation = VWO.variationName(forTestKey: "test_key") {
    switch variation {
        case "Control":
            // Code for Control
            break
        case "Variation 1":
            // Code for Variation 1
            break
        default: break
    }
}

Define Goals

In the next step, define at least one goal. A goal is a conversion matrix that we want to optimize.

conversionGoal

In the mobile app, use the following code to trigger this goal.

[VWO trackConversion:@"conversionGoal"];
VWO.trackConversion("conversionGoal")

Finalize

In the Finalize step, we can set the percentage of users that we want to include in the campaign.
Under the Advanced option, we can also target the campaign for specific user types, enable scheduling, or change traffic allocation for each variation.

For quick setup, we can leave the settings in Advanced as default.

To run the campaign, select Finish > Start Now.

Reports

In the mobile app A/B menu option, select your campaign, and then click DETAILED REPORTS to view the reports of your campaign.

Source Code

VWO iOS SDK code is available on GitHub:
https://github.com/wingify/vwo-ios-sdk

Next Steps

As the next step, look at SDK Reference to explore more advanced options of using the SDK.
We would look forward to hear from you about any question or feedback at support@vwo.com.

Suggest Edits

App and Variable

 

This section shows details on how to add your mobile app to VWO for testing.

Suggest Edits

Adding the Mobile App to Test

 

Go to the Apps section on the page.

On the right side of the screen, click Create App.
Type the name of the app you want to add, and then click Create.

As you add an app, VWO generates API Keys for both the iOS and Android platforms. You can make a note of the API Key under the Settings section which is used during app initialization.

Installing the SDK

For iOS App
You can use Cocoapods to install the VWO iOS SDK.
For Cocoapod installation, add the VWO pod to your Pod file.
Run the pod install command. Click here for detailed installation instructions.

Initializing the SDK

For iOS App
After installing the SDK, you can initialize the app in the AppDelegate file by using the didFinishLaunchingWithOptions method.
Import VWO, and then call the launchForAPIKey method by using your App Key.
Click here for detailed instructions.

Suggest Edits

Defining the Variables You Want to Test

 

Test variables are elements or parameters of your mobile app. After you define a variable, you can run an unlimited number of A/B tests on the variable, without doing any code changes or redeployment. For example, you can create a string-type variable for testing different text versions on the app screen.

Under the Apps tab, select the mobile app for which you want to create test variables.

To add an element for testing, select Variables > Create Variable.

Assign a name to the variable, and then select its data type.

Type Default Value(current value or a value if there is no A/B test).

You can view the relevant Java, Objective, or Swift code snippet in the right panel as you create the variable. You can use this code snippet to update the changes in your mobile app code.

To add the variable, touch Create. You can add multiple variables to an app.

The Default Value field helps you write consistent code, without introducing checks for nil.
In the example above, we have defined the speed integer variable with the default value as 5.
The corresponding code for Java, Objective-C, and Swift is also generated.
Now, instead of using int speed = 5; use the code below.

int speed = [VWO intForKey:@"speed" defaultValue:5];
int speed = VWO.intFor(key: "speed", defaultValue: 5)
Suggest Edits

Mobile A/B Test

 

This section shows how to create an A/B test, use variables, code blocks, and the preview mode.

Suggest Edits

Creating A/B Tests

 

Creating a mobile A/B Test requires starting a campaign on app.vwo.com, and then making corresponding changes to it in the mobile app.

On the Mobile App A/B testing screen, select Campaigns > Create.

From the Choose an app drop-down, choose the app you want to test. All mobile apps you have added to VWO are listed here.
Select a platform where the app is running.
Enter a unique identifier in the Define a test key field to filter your tests easily. The test key helps you execute the custom logic, as explained in this Code Blocks section.

Click Next.

Click Add Variable. All the variables you have created for the test are displayed here. You can choose to Create Variable by adding a new test variable.

Next, select the variable you want to test, and then enter the variation value in the relevant fields. You can test multiple variables through one test.

In the example above, we have added the speed variable, and then defined 20 as the value of the variation.

For control, the value is 10, which is the default value of the variable.

You can use the code blocks shown in the test code to run custom logic for users in control or variation.

In the Goals step of campaign creation, we can add a goal to measure the performance of variations.

In the Finalize step of campaign creation, we can control the traffic percentage, schedule a campaign, customize traffic allocation for each variation, and target the campaign for specific user groups.

Suggest Edits

Code Blocks

 

Code blocks is a powerful way to run custom logic for different variations. For tests which are not based on the existing variables of your app, code block offers a developer-friendly approach to test different variations.

The VWO SDK identifies a test by its test key. The test key should match the key you created while setting up the A/B test on the VWO web portal.

The variationName function returns the name of the variation you created on the VWO web portal.

NSString *variationName = [VWO variationNameForTestKey:@"test_key"];
if ([variationName isEqualToString:@"Control"]) {
    // Code for Control
} else if ([variationName isEqualToString:@"Variation 1"]) {
    // Code for Variation 1
} else {

}
if let variation = VWO.variationNameFor(testKey: "test_key") {
    switch variation {
        case "Control":
            // Code for Control
            break
        case "Variation 1":
            // Code for Variation 1
            break
        default: break
    }
}

The variation name should match the name you used on the VWO web portal.
Use the last else or default section to code the behavior of your app if this A/B test is not running.
If your control and default behaviors are the same, you can remove the control condition.

Suggest Edits

Variables in an A/B Test

 

Use variables to parameterize your mobile app, and then easily run A/B tests on the parameters.

Variables can be of the type:

  • Integer
  • Float
  • String
  • Boolean

Refer to the Adding a Variable section on how to create a variable.
When you select a variable in an A/B test, you need not do any code changes for that variable. The VWO SDK will fetch the values for that variable and return the value according to the variation.

If you want to update the default value of a variable, change the default value on the VWO web portal, and then use the newly generated code snippet in your mobile app.

If you are not running an A/B test, the VWO SDK returns the defaultValue you pass in the function call.

Suggest Edits

SDK Reference

 

This section is a complete reference for VWO's iOS SDK.

Read further to find out how to install iOS SDK, preview your changes, and run A/B tests.

Suggest Edits

SDK Installation

 

The iOS SDK can be installed by using CocoaPods.

CocoaPods Installation

To integrate your mobile application by using CocoaPods, first create a Podfile.
If you are new to CocoaPods, refer to the CocoaPods instruction guide.

1. Add the following line to the Podfile.

 target 'Your App' do
     pod 'VWO'
 end

2. Run the following command.

pod install

pod install installs the SDK on your project.

VWO/Core

To reduce the size of SDK, pod 'VWO/Core' can be added to the Podfile.
This will make sure that all extra code is required only while development; therefore, it is not shipped with the app.

Source Code

The VWO iOS SDK code is available on GitHub:
https://github.com/wingify/vwo-ios-sdk

Suggest Edits

Launching the SDK

 

After installing the SDK, you can initialize the VWO SDK in your mobile app.

API Key

To initialize the SDK, we will use the API key generated while Adding an App.

Initialization of the SDK is done in the AppDelegate file.

@import "VWO";
import VWO

SDK can be launched in two ways:
asynchronous and synchronous.

Asynchronous initialization does NOT block code execution while SDK fetches settings from the VWO content distribution network, but a synchronous call blocks code execution.
We recommend asynchronous initialization, because it does not affect the UI of your app.

Asynchronous Initialization

[VWO launchForAPIKey:@"<your-api-key>" config:nil completion:^{
  //Code executed after launch is complete
} failure:^(NSString * _Nonnull error) {
	// Failure handling
}];

VWO.launch(apiKey: "<your-api-key>", config: nil
  completion: {
	   //Code executed after launch is complete     
	}, failure: { error in
      print(error)
})

Launch configuration can be passed while launching the SDK. To learn more, click here.
The completion callback method is used after the SDK fetches settings from the VWO content distribution network and processes these settings.
Use callback when you want to get notified that the SDK is ready.

The following is a use case for using the callback method:
You are testing whether showing a pop-up of a discounted in-app purchase on the first screen of your app leads to increase in the number of purchases.
It would be best to show this user on the first screen of the app, as soon as the app loads. In this A/B test, your code would want to know whether this user should see a pop-up or not.
You can use the callback method, and then show the first screen on completion. You are now confident that when you ask the SDK for the settings of this campaign, the SDK will have the updated data.

Synchronous Initialization

[VWO launchSynchronouslyForAPIKey:@"your-api-key" config: nil timeout:3.0];
VWO.launchSynchronously(apiKey: "your-api-key", config: nil, timeout: 3.0)

If settings cannot be fetched in the given time, the SDK uses old settings for already saved campaigns and falls back to the defaultValue or nil for new campaign keys.

Synchronous Initialization

In synchronous initialization, a network call is done on the main thread.
We do not recommend using the synchronous mode of initialization. The synchronous method of initialization can lead to freezing of UI.

Launch the SDK Once

On launchForAPIKey or launchSynchronouslyForAPIKey calls, the SDK fetches campaign settings from the VWO content distribution network.
In case the settings cannot be fetched, the SDK doesn't retry to fetch the settings during an ongoing app session.
This is done to keep the app behavior consistent during an app session.

You should launch the SDK only by using the appDidFinishLaunchingWithOptions method.

Suggest Edits

Launch Configuration

 

You can set up VWO Config while initializing your VWO SDK. This is helpful if you want to perform the following tasks:

VWOConfig *config = [VWOConfig new];
config.optOut = YES;
config.customVariables = @{@"user" : @"free"};
config.disablePreview = YES;
config.userID = "jack@xyz.com"

[VWO launchForAPIKey:@"<your-api-key>" config:config completion:^{
  //Code executed after launch is complete
} failure:^(NSString * _Nonnull error) {
	// Failure handling
}];
let config = VWOConfig()
config.optOut = true;
config.customVariables = ["user" : "free"]
config.disablePreview = true;

VWO.launch(apiKey: "<your-api-key>", config: config
  completion: {
	   //Code executed after launch is complete     
	}, failure: { error in
      print(error)
})
Suggest Edits

Trigger Goals

 

For any campaign, we want to track conversion changes for the A/B test.

We can define goals on the VWO web portal during the campaign setup.

test_goal

Whenever a user completes an action that we want to optimize, we can trigger a goal.

[VWO trackConversion:@"test_goal"];
VWO.trackConversion(goal: "test_goal")

If you trigger the above code snippet multiple times, the SDK counts the conversions only once per user.

Types of Goals

  • Triggers custom conversion
    A custom conversion goal is used for generic events when we want to record an event for a conversion. The above example was for this goal type.
  • Generates revenue
    This goal is useful when we want to track a revenue value with the conversion event. For example, if we are testing a purchase button, we would want to track the item value.
    Code sample for generating the revenue goal:
[VWO trackConversion:@"test_goal" withValue:@100];
VWO.trackConversion(goal: "test_goal", value: 100)

Note

Your code can trigger a goal multiple times for a user, but the SDK makes sure that a conversion is only counted once per user.
This is done to avoid repetitive counting and to keep the campaign results consistent.

Suggest Edits

Preview Mode

 

The Preview mode is helpful when you make changes to your app code for a campaign. It is used to verify that a campaign is set up correctly.

Enabling the Preview Mode

The Preview mode is automatically enabled when the application is running on simulator or if a test device is connected to Xcode. The Preview mode can also be enabled by tapping with 5 fingers for 2 seconds while the application is open. The Preview button appears in the Variations and Goals steps of campaign creation.
As you can have multiple apps added to your account, make sure to select the app which you want to A/B test.

Disabling the Preview Mode

You can disable the Preview mode from VWOConfig, and then pass that config during the SDK launch.

VWOConfig *config = [VWOConfig new];
config.disablePreview = YES;

[VWO launchForAPIKey:@"api_key" config:config completion:^{
    //completion code
} failure:^(NSString * _Nonnull error) {
    //error code
}];
let config = VWOConfig()
config.disablePreview = true

VWO.launch(apiKey: "api_key", config: config, completion: {
    //Completion code
}) { (errorString) in
    //Error code
}

Skip socket library

The Preview functionality is socket based, and the socket library is installed by default. While releasing, you can skip the socket library by adding pod VWO/Core to Podfile.

Suggest Edits

Targeting Visitor Groups

 

We can target a campaign for specific users of the app.
To do this, under Advanced Options of the Finalize step of campaign creation, select Enable campaign for a specific user group.

You can target the app according to the following options:

  • iPhone Users
  • iPad Users
  • New Users
  • Returning Users
  • App Version
  • iOS Version
  • Day of Week
  • Hour of the Day
  • Country
  • Screen Width
  • Screen Height

Please note that all the above targeting options do not require any code changes.

If you want to do custom targeting such as running a campaign only for paid users of your app, then select Custom Variable.

Custom Variable

The Custom Variable field is useful when you want to target the campaign on the variables and conditions set by your code.
To use a custom variable, define a variable name and a corresponding value in the dashboard.
In your app code, set customVariables in VWOConfig before launching.

VWOConfig *config = [VWOConfig new];
config.customVariables = @{@"user" : @"paid"};

[VWO launchForAPIKey:@"<your-api-key>" config:config completion:^{
  //Code executed after launch is complete
} failure:^(NSString * _Nonnull error) {
	// Failure handling
}];
let config = VWOConfig()
config.customVariables = ["user" : "paid"]

VWO.launch(apiKey: "<your-api-key>", config: config
  completion: {
	   //Code executed after launch is complete     
	}, failure: { error in
      print(error)
})

When to set custom variables

  • If you have specified certain custom variables in the campaign, those values must be set in the code before calling the objectForKey:defaultValue: method.

  • If you have selected Make user part of the campaign on app launch in the VWO dashboard, then custom variables should be set before launching the SDK. This is required, because the SDK will try to make the user a part of the campaign on the app launch.

 

You can identify a user in the VWO SDK by using a string that identifies that user.
User ID can be set in the VWO Launch config.

User ID helps VWO identify a user across multiple devices, and allows it to serve the same variation to a user thus keeping the experience consistent.

For example, you may run a campaign on both iPhone and iPad. If a user installs both the iPhone app and iPad app, setting the user ID will allow VWO to serve the same variation for a campaign.

VWOConfig *config = [VWOConfig new];
config.userID = @"<uuid-for-the-user>";

[VWO launchForAPIKey:@"<your-api-key>" config:config completion:^{
    //completion code
} failure:^(NSString * _Nonnull error) {
    //error code
}];
let config = VWOConfig()
config.userID = "<uuid-for-the-user>"

VWO.launch(apiKey: "<your-api-key>", config: config, completion: {
    //Completion code
}) { (errorString) in
    //Error code
}

Note that altering the traffic allocation among variations or total campaign traffic can break this. Also, changing targeting while the campaign is running is also not advisable.

Please note

User ID is used as hash and is not stored anywhere on the device or server.

Suggest Edits

Integrations

 

You can send VWO's campaign information to third-party analytics platforms by using notification listeners. You can then segment the analytics report by using VWO's campaign id, campaign name, variation id, or name.

Next, you will find suggested implementations for some common analytics platforms. Feel free to use these as showcased, or adapt these to meet your specific needs.

Notification Listener

The code can listen to an NSNotification on the key VWOUserStartedTrackingInCampaignNotification.

Here is how notifications can be integrated in AppDelegate.

#import "AppDelegate.h"
@import VWO;

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    [VWO launchForAPIKey:@"8116fb11614377a61fb7eb2fa2754660-295084" completion:^{
        NSLog(@"Launch success");
    } failure:^(NSString * _Nonnull error) {
    }];

    [self addVWOObserver];

    return YES;
}

- (void)addVWOObserver {
    [NSNotificationCenter.defaultCenter addObserverForName:VWOUserStartedTrackingInCampaignNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
        NSDictionary *campaign = note.userInfo;
        NSString *campaignName = campaign[@"vwo_campaign_name"];
        NSString * campaignId = campaign[@"vwo_campaign_id"];
        NSString * variationName = campaign[@"vwo_variation_name"];
        NSString * variationId = campaign[@"vwo_variation_id"];

        NSLog(@"Campaign %@ %@", campaignName, campaignId);
        NSLog(@"Variation %@, %@", variationName, variationId);
    }];
}

@end
import VWO

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        VWO.launch(apiKey: "YOUR-API-KEY", config: nil, completion: {
            // Launch success
        }, failure: nil)

        addVWOObserver()
        return true
    }

    func addVWOObserver() {
        NotificationCenter.default.addObserver(
            forName: NSNotification.Name.VWOUserStartedTrackingInCampaign,
            object: nil, queue: nil) {
                notification in
                if let campaign = notification.userInfo as? [String : String] {
                    let campaignName = campaign["vwo_campaign_name"]!
                    let campaignId = campaign["vwo_campaign_id"]!
                    let variationName = campaign["vwo_variation_name"]!
                    let variationId = campaign["vwo_variation_id"]!
                    print("Campaign \(campaignName) \(campaignId)")
                    print("Variation \(variationName) \(variationId)")
                }
        }
    }
}

Notification Data

On receiving a notification, you can get the campaign data from the notification object which is passed to the callback.

The data contains the following keys:

  • vwo_campaign_id: Identifier of the campaign; this is generated by VWO. This is unique for your account.
  • vwo_campaign_name: Name of the campaign, as set by you. This is not necessarily unique.
  • vwo_variation_id: Identifier of the variation in the campaign of which the user became a part. Variation Id is unique for its campaign, but it is not unique across different campaigns.
  • vwo_variation_name: Name of the variation in the campaign, as set by you. This is not necessarily unique.

Amplitude

Please refer to the Amplitude iOS guide if you are getting started with Amplitude.

In the following suggested approach for Amplitude, we use Events.

We add a notification listener to listen to the notification with the key VWOUserStartedTrackingInCampaignNotification. When the callback is requested, we send an event to Amplitude when a user becomes a part of a campaign. In the event, we are sending the campaign name and id, along with the variation name and id.

Events in Amplitude take an event name and event properties in the form of a dictionary.

If the campaign name is TestSignup and campaign id is 21, we can set the event name as VWO Campaign - TestSignup - 21. We also send event parameters as campaign_name, campaign_id, variation_name, and variation_id.

[NSNotificationCenter.defaultCenter addObserverForName:VWOUserStartedTrackingInCampaignNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
   NSDictionary *campaign = note.userInfo;
   NSString *event = [NSString stringWithFormat:@"VWO Campaign - %@ - %@", campaign[@"vwo_campaign_name"], campaign[@"vwo_campaign_id"]];
   [Amplitude.instance logEvent:event withEventProperties:campaign];
}];
NotificationCenter.default.addObserver(forName: NSNotification.Name.VWOUserStartedTrackingInCampaign, object: nil, queue: nil) { (notification) in
   if let campaign = notification.userInfo as? [String : String] {
      let event = "VWO Campaign - \(campaign["vwo_campaign_name"]!) - \(campaign["vwo_campaign_id"]!)"
       Amplitude.instance().logEvent(event, withEventProperties: campaign)
   }
}

Flurry

Please refer to the Flurry iOS guide if you are getting started with Flurry.

In the following suggested approach for Flurry, we use Custom Events.

We add a notification listener to listen to NSNotification with the key VWOUserStartedTrackingInCampaignNotification. When the callback is requested, we send an event to Flurry when a user becomes part of a campaign. In the event, we are sending the campaign name and id, along with the variation name and id.

Events in Flurry have a two-level structure. The highest level is the specific action, in this case, VWO. The second level in the Events structure is the Event parameter.

If the campaign name is TestSignup and campaign id is 21, we can set the event name as VWO Campaign - TestSignup - 21. We also send event parameters as campaign_name, campaign_id, variation_name, and variation_id.

Per Flurry, prior to logging any events, you must initiate the session with one of the startSession method variants . Any events logged prior to session initialization will not be recorded.

[NSNotificationCenter.defaultCenter addObserverForName:VWOUserStartedTrackingInCampaignNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
   NSDictionary *campaign = note.userInfo;
   NSString *event = [NSString stringWithFormat:@"VWO Campaign - %@ - %@", campaign[@"vwo_campaign_name"], campaign[@"vwo_campaign_id"]];
   [Flurry logEvent:event withParameters:campaign];
}];
NotificationCenter.default.addObserver(forName: NSNotification.Name.VWOUserStartedTrackingInCampaign, object: nil, queue: nil) { (notification) in
   if let campaign = notification.userInfo as? [String : String] {
      let event = "VWO Campaign - \(campaign["vwo_campaign_name"]!) - \(campaign["vwo_campaign_id"]!)"
      Flurry.logEvent(event, withParameters: campaign)
   }
}

Google Analytics

Please refer to the Google Analytics iOS guide, if you are getting started with Google Analytics.

In the following approach for Google Analytics, we use Events.

We add a notification listener to listen to NSNotification with the key VWOUserStartedTrackingInCampaignNotification. When the callback is requested, we send an event to Google Analytics when a user becomes a part of a campaign. In the event, we are sending the campaign name and id, along with the variation name and id.

The next step is to build segments for each variation of your campaign. In the segment-builder user interface, look under Advanced and add a new Condition. Filter Users by Event Action and Event Label, enter a name for the segment, and then click Save.

Finally, build a report of metrics you are interested in.

[NSNotificationCenter.defaultCenter addObserverForName:VWOUserStartedTrackingInCampaignNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
    NSDictionary *campaign = notification.userInfo
    NSString *event = [NSString stringWithFormat:@"VWO Campaign - %@ - %@", campaign[@"vwo_campaign_name"], campaign[@"vwo_campaign_id"]];
    NSString *action = [NSString stringWithFormat:@"%@ - %@", campaign[@"vwo_campaign_name"], campaign[@"vwo_campaign_id"]];
    NSString *label = [NSString stringWithFormat:@"%@ - %@", campaign[@"vwo_variation_name"], campaign[@"vwo_variation_id"]];
  
    id<GAITracker> tracker = [GAI sharedInstance].defaultTracker;
    [tracker send:[[GAIDictionaryBuilder
                    createEventWithCategory:category
                                     action:action
                                      label:label
                                      value:nil] build]];
}];
NotificationCenter.default.addObserver(forName: NSNotification.Name.VWOUserStartedTrackingInCampaign, object: nil, queue: nil) { (notification) in
   if let campaign = notification.userInfo as? [String : String] {
      let category = "VWO Campaign - \(campaign["vwo_campaign_name"]!) - \(campaign["vwo_campaign_id"]!)"
      let action = "\(campaign["vwo_campaign_name"]!) - \(campaign["vwo_campaign_id"]!)"
      let label = "\(campaign["vwo_variation_name"]!) - \(campaign["vwo_variation_id"]!)"

      if let builder = GAIDictionaryBuilder.createEvent(withCategory: category, action: action, label: label, value: nil),
         let tracker = GAI.sharedInstance().defaultTracker {
            tracker.send(builder.build() as! [AnyHashable : Any]!)
         }   
    }
}

Google Custom Dimension

Google also offers Custom Dimensions which enables association of metadata with hits, users, and sessions in Google Analytics.

In the above approach, we only send an event to Google Analytics. You may choose to set the custom dimension. For this, refer to the Custom Dimension and Metrics section in Google Analytics and then set the custom dimension in the notification callback.

The next step is to make changes in Google Analytics. Look for the Admin option in the menu bar, and then select the appropriate account and a property. Under Property, click Custom Definitions > New Custom Dimension. Enter a unique name for the dimension, select User for the scope, and then click Create.

You can now see the reports according to the custom dimension.

Localytics

Please refer to the Localytics iOS guide if you are getting started with Localytics.

In the following suggested approach for Localytics, we use Custom event with attributes.

We add a notification listener to listen to NSNotification with key VWOUserStartedTrackingInCampaignNotification. When the callback is requested, we send an event to Localytics when a user becomes part of a campaign. In the event, we send the campaign name and id, along with the variation name and id.

Localytics also offers a way to set user attributes. You can set user attributes for VWO's campaign data as well.

The custom event in Localytics has an event name and attributes.
If the campaign name is TestSignup and campaign id is 21, we can set the event name as VWO Campaign - TestSignup - 21. We also send event parameters as campaign_name, campaign_id, variation_name, and variation_id.

[NSNotificationCenter.defaultCenter addObserverForName:VWOUserStartedTrackingInCampaignNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
   NSDictionary *campaign = note.userInfo;
   NSString *event = [NSString stringWithFormat:@"VWO Campaign - %@ - %@", campaign[@"vwo_campaign_name"], campaign[@"vwo_campaign_id"]];
   [Localytics tagEvent:event attributes:campaign];
}];
NotificationCenter.default.addObserver(forName: NSNotification.Name.VWOUserStartedTrackingInCampaign, object: nil, queue: nil) { (notification) in
   if let campaign = notification.userInfo as? [String : String] {
      let event = "VWO Campaign - \(campaign["vwo_campaign_name"]!) - \(campaign["vwo_campaign_id"]!)"
      Localytics.tagEvent(event, attributes: campaign)
   }
}

Mixpanel

Please refer to the Mixpanel iOS guide if you are getting started with Mixpanel.

In the following suggested approach for Mixpanel, we use Events. Mixpanel also offers a way to set super properties and user profiles.

We add a notification listener to listen to NSNotification with key VWOUserStartedTrackingInCampaignNotification. When the callback is requested, we send an event to Mixpanel when a user becomes part of a campaign. In the event, we send the campaign name and id, along with the variation name and id.

If you need to use super properties or people properties, modify the following code and send appropriate values to Mixpanel.

The next step is to look for VWO events in your Mixpanel account. You can look at the funnels with the VWO event or look at the segment data.

[NSNotificationCenter.defaultCenter addObserverForName:VWOUserStartedTrackingInCampaignNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
   NSDictionary *campaign = note.userInfo;
   NSString *event = [NSString stringWithFormat:@"VWO Campaign - %@ - %@", campaign[@"vwo_campaign_name"], campaign[@"vwo_campaign_id"]];
   [Mixpanel.sharedInstance track:event properties:campaign];
}];
NotificationCenter.default.addObserver(forName: NSNotification.Name.VWOUserStartedTrackingInCampaign, object: nil, queue: nil) { (notification) in
   if let campaign = notification.userInfo as? [String : String] {
      let event = "VWO Campaign - \(campaign["vwo_campaign_name"]!) - \(campaign["vwo_campaign_id"]!)"
      Mixpanel.mainInstance().track(event: event, properties: campaign)
   }
}

Segment

Please refer to the Segment iOS guide if you are getting started with Segment.

Segment has a spec for A/B testing events.

We add a notification listener to listen to NSNotification with the key VWOUserStartedTrackingInCampaignNotification. When the callback is requested, we send an event to Segment when a user becomes part of a campaign. In the event, we are sending the campaign name and id, along with the variation name and id.

If the campaign name is TestSignup and campaign id is 21, we can set the event name as Experiment Viewed. We also send event parameters as experimentId, experimentName, variationId, and variationName.

[NSNotificationCenter.defaultCenter addObserverForName:VWOUserStartedTrackingInCampaignNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
   NSDictionary *campaign = note.userInfo;
   NSString *event = [NSString stringWithFormat:@"VWO Campaign - %@ - %@", campaign[@"vwo_campaign_name"], campaign[@"vwo_campaign_id"]];
   NSDictionary *properties = @{
       @"experimentId"   : campaign[@"vwo_campaign_id"],
       @"experimentName" : campaign[@"vwo_campaign_name"],
       @"variationId"    : campaign[@"vwo_variation_id"],
       @"variationName"  : campaign[@"vwo_variation_name"]
    };
    [SEGAnalytics.sharedAnalytics track:event properties:properties];
}];
NotificationCenter.default.addObserver(forName: NSNotification.Name.VWOUserStartedTrackingInCampaign, object: nil, queue: nil) { (notification) in
   if let campaignDict = notification.userInfo as? [String : String] {
      let event = "VWO Campaign - \(campaign["vwo_campaign_name"]!) - \(campaign["vwo_campaign_id"]!)"
      let properties = [
         "experimentId"   : campaign["vwo_campaign_id"]!,
         "experimentName" : campaign["vwo_campaign_name"]!,
         "variationId"    : campaign["vwo_variation_id"]!,
         "variationName"  : campaign["vwo_variation_name"]!
      ]
      SEGAnalytics.shared().track(event, properties: properties)
   }
}
 

To enable logging in SDK, use [VWO.setLogLevel: level].
You can set different log levels depending upon the priority of logging as follows:

  • Debug: Gives detailed logs.
  • Info: Informational logs
  • Warning: Warning is a message level indicating a potential problem.
  • Error: Indicates Error
  • None: No logs are printed

The different methods set the log level of the message. VWO will only print messages with a log level that is greater to or equal to it's current log level setting. So a logger with a level of Warning will only output log messages with a level of Warning, or Error.

[VWO.setLogLevel: VWOLogLevelWarning];
VWO.logLevel = .warning
 

To opt out of tracking by VWO, use setOptOut:YES method on users you don’t want to be tracked.

VWOConfig *config = [VWOConfig new];
config.optOut = YES;

[VWO launchForAPIKey:@"<your-api-key>" config:config completion:^{
  //Code executed after launch is complete
} failure:^(NSString * _Nonnull error) {
	// Failure handling
}];
let config = VWOConfig()
config.optOut = true;

VWO.launch(apiKey: "<your-api-key>", config: config
  completion: {
	   //Code executed after launch is complete     
	}, failure: { error in
      print(error)
})

A user by default will be tracked by VWO.

 

Using the VWO demo app, you can try Mobile App A/B testing.
To try the demo app, you will need ApiKey.

Running the Demo App

Clone the demo app from https://github.com/wingify/vwo-ios-sdk
Browse to vwo-ios-sdk/Demo
Run pod install

Enter ApiKey

You need to add an app to your VWO account. Please refer to Adding an App for details.
Copy your ApiKey.
Run the app from Xcode. You can choose either a simulator or your iPhone.

When the app is running, click the Menu icon in the upper-left corner.

Select Enter API Key from the menu options, and then paste your api key.
If you using a simulator, you can use Command ⌘ + Shift ⇧ + V to paste your api key in the text box.

Xcode launch parameters

Developers can use Xcode launch parameters to test the app.
Step to launch:

  1. Open Edit Scheme (Command ⌘ + Shift ⇧ + <)
  2. Run → Arguments → Arguments Passed on Launch
  3. Click on + sign and add your API in format -VWOApiKey <your-api-key>
  4. Close

When you run your app after setting launch argument, it should appear pre filled in launch alert

APIKey in launch will not launch VWO

Adding your API Key to the launch parameter will only make your work easy by automatically adding the API key to the input text field. Developer will have to manually launch the app separately.

Sorting Campaign

Showing a list of items is a common requirement for many apps.
How do you know what sequence is better? What better way to tell than to A/B test!

Defining Variation

Steps to run Sorting Campaign:

  1. Under Mobile App A/B, click Create Menu and then choose your App, platform and set test key to "sorting". Click Next for Variations screen.
  2. On the Variations screen, update the variation names as seen in the image below

In your app, click the Refresh icon located in the upper-right corner of the navigation bar.
This should change the sequence of items

Following code handles the A/B testing for Sorting campaign

let variation = VWO.variationNameFor(testKey: "sorting")
switch variation {
case "Sort-Alphabetically":
    phoneList.sort(by: sortPhoneAlphabetically)
case "Sort-By-Price":
    phoneList.sort(by: sortPhoneByPrice)
default:
    print("Default")
    break
}
tableView.reloadData()

The code above does following things

  1. Get the variation name for campaign whose test key is "sorting"
  2. Depending on the variation name we decide if the sorting is to be done alphabetically or by price
  3. Once the list is sorted we reload the table data

Defining Goals

Click Next, and then define a goal using the following goal identifier.

We can see if the goals work correctly.
Click Verify.

Select your device from the drop-down menu.

On selecting any product (phone) from the list, you can see the product details.

When you select the product, Goal 1 becomes Verified.

This happens because, we have placed VWO.trackConversion( "productView") code upon selecting a product.

If you want to verify the goal for variation, select Variation from the drop-down menu, select refresh in the app, and then repeat the same process.

Finalize Campaign

Click Next to move to the final stage of campaign creation. You can set percentage traffic allocation and then do advance targeting.

To start the campaign, click Finish.

Variable Campaign

How do you know what content would appeal to your users
This campaign helps us test various alerts by presenting various titles and content

Defining Variation

Steps to run Layout Campaign:

  1. Under Mobile App A/B, click Create and then choose your mobile app.
  2. In the Variations screen, create variable named heading and content of String type
  3. Set the values accordingly
  4. You can use the code generated on right side

After creating the variables add them to your campaign and set values accordingly

Select your device from the options(three dots), and then select Preview on Device.

In your app, click on any house in the list and you can verify the look and feel of all the variation
The variation section of the demo app will change.

Defining Goals

Click Next and then define a goal using the following goal identifier.

We can see if goals work correctly.
Click Verify.

From the device drop-down menu, select your device.

When you tap on upgrade button in the alert, the goal will get verified

This happens because , we have placed VWO.markConversionFor(goal: "upgrade-clicked") code on tapping the upgrade button.

If you want to verify the goal for the variation, select Variation from the Control drop-down menu and then tap on Upgrade button in alert

Finalize Campaign

To move to the final stage of campaign creation, click Next. Now, you can set percentage traffic allocation and perform advance targeting.

To start the campaign, click Finish.

Q. What's the minimum iOS version supported by the SDK?

iOS SDK supports iOS version 8.0 and later.

Does VWO support apps written in Swift?

Yes, the SDK works with Swift. This documentation mentions all the Swift methods.

Q. What happens if there is no internet connectivity?

A user will become part of a test only if the device has internet connectivity. If there is no connectivity, the user sees the default version (Control) of the app.

If the user is part of the test and connectivity is lost, the user will see locally cached changes. In this case, the VWO SDK captures the user data, stores it locally, and resends the data to the VWO server when the device gets connected to the Internet again.

Q. How much size does the VWO Mobile SDK add to my app size?

Please refer to iOS Impact Analysis section to see the impact of different parameters on your app.

Q. How do I deactivate the SDK?

You can either comment out the SDK initialization function call or remove the VWO SDK for deactivating the SDK.

Q. Can I run simultaneous tests on the same app?

Yes, you can run simultaneous tests on the same app. A user accessing the app will automatically become part of all the tests running on your app, subject to target segment conditions.

Q. Can I test multiple apps?

Yes, you can test unlimited apps and create unlimited campaigns on these apps.

Suggest Edits

Impact Analysis

 

This page tracks the impact of VWO iOS SDK for different parameters on your app.

Launch Time

The SDK can be initialised in two ways: synchronous and asynchronous.

  • Asynchronous Initialisation: has no impact on the launch time of your app, as SDK is launched in the background. Asynchronous initialisation is the recommended method.
  • Synchronous Initialisation: In Synchronous initialisation the SDK makes a networking call to fetch settings from VWO's CDN. This can block the main thread. The thread resumes to normal execution after response from the CDN.

API Calls

VWO SDK makes three types of API calls to VWO CDN.

  • To fetch settings at the time of SDK initialization. The SDK makes only one call to fetch settings. If this call fails, the SDK does not retry to fetch settings during an ongoing app session. This is done to keep the app behaviour consistent during an ongoing session.
  • To inform VWO when a user becomes part of a campaign. If this call fails, the SDK keeps a track of it and try to send it again after some time.
  • To inform VWO when a user converts a goal in a campaign. If this call fails, the SDK keeps a track of it and try to send it again after some time.

The SDK makes call to CDN every 20 seconds.

Disk Space

After adding VWO to you Xcode project the size of Xcode project changes as follows

Installation type
Size

VWO/Core

~ 284 KB

VWO

~ 800 KB

Increase in IPA file size

Installation type
Size

VWO/Core

~ 100 KB

VWO

~ 700 KB

RAM Usage

Method
Memory usage (in KBs approx)

launchForAPIKey:config:completion:

300

launchSynchronouslyForAPIKey:config:timeout

350

objectForKey: defaultValue:
intForKey:defaultvalue:
floatForKey:defaultValue
boolForKey:defaultValue

less than 1

trackConversion

less than 1

trackConversion: withValue:

less than 1

If you want to know the impact of any other parameter or if you want to understand anything around it, please reach out to us: support@vwo.com

Suggest Edits

Quick Start Guide

 

To create and run A/B tests, sign in to the VWO dashboard and then select Mobile App A/B on the menu. If you are using the VWO A/B testing feature for the first time, click Start Mobile App A/B Testing to begin.

To create A/B tests for mobile apps:

Add the mobile app to be tested.

Define the variables you want to test.

Create A/B tests.

Add the mobile app to be tested

To add a new app for A/B testing, go to the Apps section on the page.

On the right side of the screen, click Create App.
Type the name of the app you want to add, and then click Create.

As you add an app, VWO generates API Keys for both the iOS and Android platforms. You can make a note of the API Key under the Settings section and are used during app initialization.

Installing SDK

You can use Gradle to install the VWO Android SDK by adding VWO SDK dependency in your build.gradle file. Click here for detailed installation instructions.

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.vwo:mobile:2.4.2@aar'
    compile ('io.socket:socket.io-client:1.0.0') {
        // excluding org.json which is provided by Android
        exclude group: 'org.json', module: 'json'
    }  
  	// Skip this if you are already including support library in your app.
    compile 'com.android.support:support-core-utils:27.1.1'
}

Add following permissions to your AndroidManifest.xml file

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

After installing the SDK, you can initialize the app in the onCreate function of the activity or the application. Click here for detailed instructions.

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.vwo.mobile.VWO;

public class MainActivity extends AppCompatActivity {
  private static final String VWO_API_KEY = "YOUR_VWO_API_KEY";

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Start VWO SDK in Async mode with callback
    VWO.with(this, VWO_API_KEY).launch(new VWOStatusListener() {
      @Override
      public void onVWOLoaded() {
        // VWO loaded successfully
      }
      @Override
      public void onVWOLoadFailure(String reason) {
        // VWO not loaded
      }
    });
  }
}
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import com.vwo.mobile.VWO
  
class MainActivity : AppCompatActivity() {
  private val VWO_API_KEY = "YOUR_VWO_API_KEY"

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    // Start VWO SDK in Async mode with callback
    VWO.with(this, VWO_API_KEY).launch(object : VWOStatusListener {
      override fun onVWOLoaded() {
        TODO("not implemented")
      }

      override fun onVWOLoadFailure(error: String?) {
        TODO("not implemented")
      }

    })
  }
}

Defining the Variables You Want To Test

Test variables are elements or parameters of your mobile app. After you define a variable, you can run an unlimited number of A/B tests on the variable, without doing any code changes or redeployment. For example, you can create a string-type variable for testing different text versions in the app screen.

Under the Apps tab, select the mobile app for which you want to create test variables.

To add an element for testing, under Variables section, click Create Variable.

Assign a name to the variable, and then select its data type.

Type Default Value (current value or a value if there is no A/B test).

To add the variable, click Create. You can add multiple variables to an app.

You can view the relevant Java, Objective, or Swift code snippet in the right panel as you create the variable. You can use this code snippet to update the changes in your mobile app code.

In your mobile app, use the code snippet for your app variables. For example, instead of using int speed = 5; use the below code.

int speed = VWO.getIntegerForKey("speed", 5);
val speed = VWO.getIntegerForKey("speed", 5)

Creating A/B Tests for Mobile Apps

On the Mobile App A/B testing screen, go to the Campaigns tab, and then click Create.

Choose the App you want to test. All mobile apps you have added to VWO are listed here.

Select a platform where the app is running.

Enter a unique identifier in the Define a test key field to filter your tests easily. The test key helps you execute custom logic, as explained in this Code Blocks section.

Select Next and click Add Variable. All the variables you have created for the test are displayed here. You can choose to Create Variable by adding a new test variable.

Select the variable you want to test, and then enter the variation values. You can test multiple variables in one test. In the example above, we have added speed variable, defined value as 20 for the variation. For control, the value is 10, which is the default value for the variable.

Based on the test key and variation names, VWO generates the code snippet that you can use in the mobile app.

To continue, click Next.

String variationName = VWO.getVariationNameForTestKey("test_key");
if (variationName != null && variationName.equals("Control")) {
   // TODO: code for Control variation
} else if(variationName != null && variationName.equals("Variation 1")) {
   // TODO: code for Variation 1
} else {
   // TODO: default case
}
val variationName = VWO.getVariationNameForTestKey("test_key")
if (variationName != null && variationName == "Control") {
  // TODO: code for Control variation
} else if (variationName != null && variationName == "Variation 1") {
  // TODO: code for Variation 1
} else {
  // TODO: default case
}

Define Goals

In the next step, define at least one goal. Goal is a conversion matrix that we want to optimize.

conversionGoal

In the mobile app, use the code below to trigger this goal.

VWO.trackConversion("conversionGoal");
VWO.trackConversion("conversionGoal")

Finalize

In the Finalize step, we can set the percentage of users that we want to include in the campaign.
Under the Advanced option, we can also target the campaign for specific user types, enable scheduling, or change traffic allocation for each variation.
For quick setup, we can leave the settings in Advanced as default.

To run the campaign, click Finish > Start Now.

Reports

From the Mobile App A/B menu option, select your campaign and click on DETAILED REPORTS to see reports of your campaign.

Source Code

VWO Android SDK code is available on GitHub:
https://github.com/wingify/vwo-android

Next Steps

As a next step, take a look at SDK Reference to look at more advanced options of using the SDK.
We would look forward to hear from you about any question or feedback at support@vwo.com.

Suggest Edits

App and Variable

 

This section shows details on how to create a mobile app and variables.
Read further for more details.

Suggest Edits

Adding an App

 

Before you can A/B test your mobile app, register it with VWO.
Registering an app is a one-time process.

From the Test menu, select Mobile App A/B.
(https://app.vwo.com/#/test/mobile-ab)

Click APPS in the upper-right corner of the page.

Click on CREATE APP on the right-hand side.

Type the name of your app and click CREATE.

After you create an app, you can see the iOS and Android API Key for both the platforms.
You will use this API Key during app initialisation.

Suggest Edits

Adding a Variable

 

Use Variables to parameterize your mobile app and easily run A/B tests on the parameters.
Variables can be defined in the VWO interface, and then used in your app. Once you define a variable, you can run an unlimited number of A/B tests on that variable, without any code changes or deploy.

Variables can be of type integer, float, string or boolean.
To create a variable, click on APPS section in Mobile App A/B.

Use Create Variable button

Enter the name of the variable, data type and a default value.
The default value is the original value for that variable. Default value gets used if there are no tests running.

Default value helps your write consistent code, without introducing checks for nil.
In the example above, we have defined speed integer variable with 5 default value.
The corresponding code for Java, Objective-C and Swift is also generated.
Now instead of using int speed = 5; use the below code.

int speed = VWO.getIntegerForKey("speed", 5);