CreativeQA.io
Indispensable QA tools & APIs
Free Web Service
API v3.0
settings_system_daydream
HTML5 Validator
settings_ethernet
Ad Tag Tester
play_circle_outline
VAST Inspector
view_compact
Banner Ad Piler
flare
HTML5 Optimizer
photo_camera_back
HTML5 Backup Ads
landscape
Image Cruncher
menu

API v3.0 Introduction

Your API Endpoint

https://{your_name}.api.creativeqa.net

Hook up your server and automatically scan creatives before they go live. The API is organized around REST, and returns JSON for all responses.

Find your API endpoint URL here at the right.

Getting an API Key

To get an API Key, ask one via support. A key will be emailed within minutes.

Authentication

Add your API Key as a header

# Add the Authorization header to each request
curl "https://{your_name}.api.creativeqa.net"
  -H "X-ApiKey: {api_key}"
  -X POST

API Keys are used to authenticate requests. Add your key to each request as a header with the name X-ApiKey. Keep your API key private as much as you do with passwords.

Rate Limits

Rate limits are calculated dynamically based on the load of the worker nodes. If no resources are available, the API will respond with a 400 HTTP code and an error message. It's generally recommended to wait for a response before sending a new one. To process batches of tags, submit them one by one instead of all at the same time.

Error Handling

Example of an error

{
    "error_type": "payload_error",
    "message": "There was an error."
}

Conventional HTTP response codes are used to indicate if a request failed or was successful. Codes in the 2xx range indicate success. Codes in the 4xx range indicate that the request failed. In that case, the JSON response will hold an error code and human-readable error message.

Error Types

authentication_error
string, solvable
The X-ApiKey header was not added or the key was incorrect. Contact support if you need help.
license_error
string, solvable
Your license has not been approved or has expired. Contact support for more information.
invalid_endpoint
string, solvable
An incorrect endpoint URL was used. Check for typos and make sure to use the endpoints from this documentation.
payload_error
string, solvable
The payload contained missing parameters or had an incorrect format. See the error message for details.
timeout
string, solvable
It took too long for the creative to load. Increase the default timeout manually if you wish to run the scan for a longer time.
processing_error
string, not solvable
The worker nodes weren't able to process your request. Please drop us a note to see if we could troubleshoot.

Change Log

Changes to the API are generally backwards compatible. If non-backwards compatible changes are introduced, the API version number in your endpoint URL will go up. Once you've reviewed the changelog and made the necessary changes at your side, you're invited to use the new API version by updating your endpoint URL accordingly.

HTML5 Zip Validator

Run a new scan

curl "https://{your_name}.api.creativeqa.net/v3.0/scan/zip"
  -H "X-ApiKey: {api_key}"
  -X POST
  -d '{
    "data": "WW91ciB6aXAgYmluYXJ5IGhlcmUuLi4="
}'

Example response

{
    "3pas": "",
    "blocked_by_adblock": false,
    "click_tag_found": true,
    "console": {
        "errors": ["Error: ReferenceError: somefunction is not defined"],
        "warnings": []
    },
    "cookies": [{
        "domain": ".creativeqa.io",
        "expires": 1646483649,
        "httpOnly": false,
        "name": "__gads",
        "path": "\/",
        "priority": "Medium",
        "secure": false,
        "session": false,
        "size": 92,
        "value": "ID=1a98edadd0995906-22cd64eb62ba0089:T=1612787649:S=ALNI_MYy4JVsyP7DbDydn73L6WR0-fHnKA"
    },
    {
        "domain": ".doubleclick.net",
        "expires": 1646483650.085365,
        "httpOnly": true,
        "name": "IDE",
        "path": "\/",
        "priority": "Medium",
        "sameSite": "None",
        "secure": true,
        "session": false,
        "size": 70,
        "value": "AHWqTUlqh0OPFbGUeGXQqkXebE_Tf9xEs0i7fspXWBfoQHL0p3ooP5Iv-vx7JYmWKsA"
    }],
    "cpu_usage": 66,
    "creative_rendered": true,
    "dialogs": [],
    "dimensions": {
        "height": 90,
        "width": 728
    },
    "dom_content_loaded": 162,
    "file_structure": [{
        "bytes": 3922,
        "name": "front_city.png",
        "type": "image"
    },
    {
        "bytes": 11860,
        "name": "index.html",
        "type": "html"
    },
    {
        "bytes": 6510,
        "name": "google_logo.png",
        "type": "image"
    }],
    "has_border": false,
    "has_external_assets": false,
    "has_video": false,
    "iframes": 1,
    "local_storage": [],
    "memory_usage": 2400256,
    "meta": {
        "api_version": "v3.0",
        "cpu": "AMD 16-Core EPYC 7302P",
        "creative_type": "zip",
        "device": "Desktop",
        "language": "en-US",
        "ram": "128GB",
        "scan_duration": "1.871964",
        "server_location": "ams",
        "timestamp": 1612789956,
        "ua": "Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/87.0.4280.88 Safari\/537.36"
    },
    "meta_ad_size": false,
    "mobile_friendly": false,
    "network": {
        "load_size": {
            "host_initiated_subload": 0,
            "initial_load": 35690,
            "total": 35690
        },
        "responses": [{
            "bytes": 11860,
            "headers": {
                "content-encoding": "br",
                "content-type": "text\/html",
                "date": "Mon, 08 Feb 2021 13:12:34 GMT",
                "last-modified": "Sat, 18 Apr 2020 18:08:16 GMT"
            },
            "is_pixel": false,
            "method": "GET",
            "resource_type": "document",
            "server_ip": "127.0.0.1",
            "ssl": true,
            "ssl_info": {
                "protocol": "TLS 1.3",
                "validFrom": 1607455037,
                "validTo": 1922815037
            },
            "status": 200,
            "status_text": "",
            "timing": 169,
            "url": "https:\/\/www.creativeqa.io\/tmp\/7febf-e5693-1b71c-78616.zip\/index.html"
        },
        {
            "bytes": 6510,
            "headers": {
                "accept-ranges": "bytes",
                "content-length": "6510",
                "content-type": "image\/png",
                "date": "Mon, 08 Feb 2021 13:12:34 GMT",
                "last-modified": "Sat, 18 Apr 2020 18:08:16 GMT"
            },
            "is_pixel": false,
            "method": "GET",
            "resource_type": "image",
            "server_ip": "127.0.0.1",
            "ssl": true,
            "ssl_info": {
                "protocol": "TLS 1.3",
                "validFrom": 1607455037,
                "validTo": 1922815037
            },
            "status": 200,
            "status_text": "",
            "timing": 201,
            "url": "https:\/\/www.creativeqa.io\/tmp\/7febf-e5693-1b71c-78616.zip\/google_logo.png"
        },{
            "..."
        }]
    },
    "job_id": "7febf-e5693-1b71c-78616",
    "score": 93,
    "screenshot": {
        "highres": {
            "bytes": 132,
            "color": "#d8ecfe",
            "mime_type": "image\/png",
            "url": "https:\/\/try.cdn.creativeqa.net\/img\/qa-report-983243-29cbfuzn4mhk.png"
        },
        "thumbnail": {
            "bytes": 538,
            "color": "#d8ecfe",
            "mime_type": "image\/jpg",
            "url": "https:\/\/try.cdn.creativeqa.net\/img\/qa-report-983243-xz5rs8mc3yuk.jpg"
        }
    },
    "ssl": {
        "compliant": true,
        "insecure_urls": []
    },
    "tests": {
        "3pas": {
            "actual": "",
            "data_type": "string",
            "expected": "Any on list",
            "message": "No click tracking macro has been detected.",
            "name": "3PAS Vendor",
            "result": "ignored",
            "unit": ""
        },
        "dimensions": {
            "actual": "728x90",
            "data_type": "string",
            "expected": "On acceptable list",
            "message": "This creative has dimensions 728 x 90, which is a standard size.",
            "name": "Ad Dimensions",
            "result": "passed",
            "unit": ""
        },
        "adblock": {
            "actual": false,
            "data_type": "boolean",
            "expected": "false",
            "message": "This tag will likely not be blocked by ad blockers.",
            "name": "Blocked by AdBlock",
            "result": "passed",
            "unit": ""
        },
        "cpu": {
            "actual": 66,
            "data_type": "int",
            "expected": "< 100 ms",
            "message": "CPU usage is acceptable at 66 ms.",
            "name": "CPU Usage",
            "result": "passed",
            "unit": "ms"
        },
        "blocked_by_heavy_ad_intervention": {
            "actual": false,
            "data_type": "boolean",
            "expected": "< 15 seconds CPU and < 4 MB load size",
            "message": "This ad is not considered heavy, and probably will pass Chrome's Heavy Ad Intervention policy.",
            "name": "Chrome's Heavy Ad Intervention",
            "result": "passed",
            "unit": ""
        },
        "click_tag_found": {
            "actual": true,
            "data_type": "boolean",
            "expected": "true",
            "message": "The clickTag for click tracking has been found in the main HTML document.",
            "name": "Click Tag",
            "result": "passed",
            "unit": ""
        },
        "click_tracking_macro": {
            "actual": "",
            "data_type": "string",
            "expected": "Any on list",
            "message": "No click tracking macro has been detected.",
            "name": "Click Tracking Macro",
            "result": "ignored",
            "unit": ""
        },
        "console_warnings": {
            "actual": 0,
            "data_type": "array",
            "expected": "0 warnings",
            "message": "No console warnings have been detected.",
            "name": "Console Warnings",
            "result": "passed",
            "unit": ""
        },
        "cookies": {
            "actual": 0,
            "data_type": "array",
            "expected": "0 cookies",
            "message": "This ad doesn't seem to drop cookies.",
            "name": "Cookies Dropped",
            "result": "passed",
            "unit": ""
        },
        "has_border": {
            "actual": false,
            "data_type": "boolean",
            "expected": "true",
            "message": "This creative doesn't have a high-contrasting border.",
            "name": "Creative Border",
            "result": "ignored",
            "unit": ""
        },
        "creative_rendered": {
            "actual": true,
            "data_type": "boolean",
            "expected": "true",
            "message": "The creative was loaded successfully.",
            "name": "Creative Rendered",
            "result": "passed",
            "unit": ""
        },
        "dialogs": {
            "actual": 0,
            "data_type": "boolean",
            "expected": "0 dialogs",
            "message": "No interruptive dialogs have been detected.",
            "name": "Dialogs & Modals",
            "result": "passed",
            "unit": ""
        },
        "has_external_assets": {
            "actual": false,
            "data_type": "boolean",
            "expected": "false",
            "message": "This creative doesn't load assets from external domains.",
            "name": "External Assets",
            "result": "passed",
            "unit": ""
        },
        "host_initiated_subload": {
            "actual": 0,
            "data_type": "int",
            "expected": "< 1048576 bytes",
            "message": "The host-initiated subload is acceptable at 0.00 KB.",
            "name": "Host-initiated Subload",
            "result": "passed",
            "unit": "bytes"
        },
        "iframe_count": {
            "actual": 1,
            "data_type": "int",
            "expected": "<= 3 iframes",
            "message": "This creative uses 1 iframes.",
            "name": "Iframe Count",
            "result": "passed",
            "unit": ""
        },
        "initial_load": {
            "actual": 35690,
            "data_type": "int",
            "expected": "< 1048576 bytes",
            "message": "The initial load size is acceptable at 34.9 KB.",
            "name": "Initial Load",
            "result": "passed",
            "unit": "bytes"
        },
        "js_errors": {
            "actual": 0,
            "data_type": "array",
            "expected": "0 errors",
            "message": "No JavaScript errors have been detected.",
            "name": "JavaScript Errors",
            "result": "passed",
            "unit": ""
        },
        "load_size": {
            "actual": 35690,
            "data_type": "int",
            "expected": "< 1048576 bytes",
            "message": "The load size is acceptable at 34.9 KB.",
            "name": "Load Size (Total)",
            "result": "passed",
            "unit": "bytes"
        },
        "dom_content_loaded": {
            "actual": 162,
            "data_type": "int",
            "expected": "< 1000 ms",
            "message": "The DOMContentLoaded event fired after 162 ms.",
            "name": "Load Speed",
            "result": "passed",
            "unit": "ms"
        },
        "local_storage": {
            "actual": 0,
            "data_type": "int",
            "expected": "0 localStorage objects",
            "message": "This ad doesn't seem to use HTML5 localStorage.",
            "name": "Local Storage",
            "result": "passed",
            "unit": ""
        },
        "memory": {
            "actual": 2400256,
            "data_type": "int",
            "expected": "< 5242880 bytes",
            "message": "Memory usage is acceptable at 2 MB.",
            "name": "Memory Usage",
            "result": "passed",
            "unit": "bytes"
        },
        "meta_ad_size": {
            "actual": false,
            "data_type": "boolean",
            "expected": "true",
            "message": "The meta tag 'ad.size' is not found in the HEAD. See the IAB guidelines.",
            "name": "Meta tag 'ad.size'",
            "result": "failed",
            "unit": ""
        },
        "missing_assets": {
            "actual": 0,
            "data_type": "boolean",
            "expected": "No 40x HTTP status codes",
            "message": "All HTTP requests were valid.",
            "name": "Missing Assets",
            "result": "passed",
            "unit": ""
        },
        "mobile_friendly": {
            "actual": false,
            "data_type": "boolean",
            "expected": "true",
            "message": "This 728 x 90 creative is not responsive on mobile devices.",
            "name": "Mobile Friendly",
            "result": "failed",
            "unit": ""
        },
        "network_requests": {
            "actual": 8,
            "data_type": "int",
            "expected": "<= 15 requests",
            "message": "A total of 8 HTTP requests were made (including pixels).",
            "name": "Network Requests",
            "result": "passed",
            "unit": ""
        },
        "pixels_fired": {
            "actual": 0,
            "data_type": "int",
            "expected": "< 5 pixels",
            "message": "This creative fires 0 pixels.",
            "name": "Pixels Fired",
            "result": "passed",
            "unit": ""
        },
        "has_video": {
            "actual": false,
            "data_type": "boolean",
            "expected": "true or false",
            "message": "This ad doesn't seem to play videos.",
            "name": "Plays Video",
            "result": "passed",
            "unit": ""
        },
        "ssl_compliant": {
            "actual": true,
            "data_type": "boolean",
            "expected": "true",
            "message": "All requests are loaded over https, including pixels and images.",
            "name": "SSL-Compliant",
            "result": "passed",
            "unit": ""
        },
        "document_write": {
            "actual": false,
            "data_type": "boolean",
            "expected": "false",
            "message": "This creative doesn't use document.write().",
            "name": "Uses document.write()",
            "result": "passed",
            "unit": ""
        },
        "visual_artifacts": {
            "actual": false,
            "data_type": "boolean",
            "expected": "false",
            "message": "No dimension discrepancies have been detected.",
            "name": "Visual Artifacts",
            "result": "passed",
            "unit": ""
        }
    },
    "uses_document_write": false,
    "visual_artifacts": false,
    "json": {
        "url": "https:\/\/try.cdn.creativeqa.net\/img\/qa-report-983243-4n9vhsar26uk.json"
    }
}

Use this scan to validate HTML5 ads in Zip format. Add the binary Zip file as a base64-encoded string to your API request.

Endpoint

POST https://{your_name}.api.creativeqa.net/v3.0/scan/zip

Arguments

data
string, required
The binary Zip file in base64-encoded format. The maximum size for this string is 10MB.
server_location
string
The location of the server used to scan the creative:
  • sfo for San Francisco (USA)
  • wdc for Washington DC (USA)
  • ams for Amsterdam (The Netherlands)
  • fra for Frankfurt (Germany)
  • sgp for Singapore
Defaults to the server the closest to the source from which the API request was made.
timeout
int
Timeout in seconds after which the scan will be canceled.
Range: 10 - 120. Defaults to 60 seconds.

Returns

3pas
string
The name of the third-party ad server, if detected successfully. Remains blank otherwise.
blocked_by_adblock
boolean
Whether or not the tag will likely be blocked by ad blockers.
click_tag_found
boolean
Whether or not a click tag was found in the index.html file.
console
array
All errors and warnings generated while loading the creative.
cookies
array
All cookies that were dropped by the creative, either set via JavaScript or via an HTTP header.
cpu_usage
int
The CPU usage, in milliseconds.
creative_rendered
boolean
Equals true in case something was painted on the screen, false otherwise.
dialogs
array
Any dialog message the creative shows as a pop-up. Generally created by alert() and confirm().
dimensions
array
The detected width and height of the creative.
dom_content_loaded
int
The time it took for the DOMContentLoaded event to fire, in milliseconds.
file_structure
array
Contains the file structure of the Zip, including the name, type and file size.
has_border
boolean
Whether or not the creative has a contrasting border.
has_external_assets
boolean
Whether or not the creative loads assets from outside the Zip. Keep this at a minimum to reduce additional DNS lookups, connections, etc.
has_video
boolean
Whether or not the creative plays video content.
iframes
int
The number of iframes added to the DOM. This should be kept at a minimum to reduce memory usage.
local_storage
array
All key/value pairs stored in window.localStorage.
memory_usage
int
The amount of RAM memory used, in bytes.
meta
array
Meta-data about the scan, like the CPU used, the time it took to complete the scan, the server location, etc.
meta_ad_size
boolean
Whether or not the creative has a <meta name="ad.size" content="width=X,height=X"> tag, as per IAB standards.
mobile_friendly
boolean
Whether or not the creative will display fine on a mobile device. Equals true if the creative is responsive or < 300 pixels wide.
network
array
All network requests and their responses, including a full echo of the HTTP headers. Provides SSL certificate information too.
job_id
string
A unique ID assigned to the scan. Store this ID on your own backend to re-fetch result data at a later moment.
score
int
The score, calculated based on the number of failed/passed tests.
screenshot
array
A screenshot of the creative. The url points to a PNG image. The background_color is in hex-format. It generally goes well with the main colors of the screenshot.
ssl
boolean
Whether or not the creative is SSL-compliant. If the creative tries to load assets over http, it will equal false.
tests
array
The most important part of the JSON response: an array of all tests conducted and their results. You can use this array to create your own report.
uses_document_write
boolean
Whether or not the creative uses the JS document.write() function. Synchronous code should be avoided.
visual_artifacts
boolean
If visual artificats have been detected. For example, a 300x250 creative that is actualy 301x251 in size.
json
array
The url contains a link to the JSON result of the scan. Great for manual downloads and inspection.

Retrieve a scan

curl "https://{your_name}.api.creativeqa.net/v3.0/jobs/{job_id}"
  -H "X-ApiKey: {api_key}"
  -X GET

Example response

{
    "3pas": "",
    "blocked_by_adblock": false,
    "click_tag_found": true,
    "..."
}

To retrieve a cached JSON response of a creative you've previously scanned, use the following endpoint. Make sure to use GET as a method. The job_id can be found in the response from a new scan.

Endpoint

GET https://{your_name}.api.creativeqa.net/v3.0/jobs/{job_id}

Returns

response
object
The full JSON response from the original scan.

Ad Tag Validator

Run a new scan

curl "https://{your_name}.api.creativeqa.net/v3.0/scan/tag"
  -H "X-ApiKey: {api_key}"
  -X POST
  -d '{
    "data": "WW91ciBhZCB0YWcgaGVyZS4uLg=="
}'

Example response

{
    "3pas": "Google Ad Manager (GAM)",
    "blocked_by_adblock": true,
    "console": {
        "errors": ["Error: ReferenceError: somefunction is not defined"],
        "warnings": []
    },
    "cookies": [{
        "domain": ".creativeqa.io",
        "expires": 1646483649,
        "httpOnly": false,
        "name": "__gads",
        "path": "\/",
        "priority": "Medium",
        "secure": false,
        "session": false,
        "size": 92,
        "value": "ID=1a98edadd0995906-22cd64eb62ba0089:T=1612787649:S=ALNI_MYy4JVsyP7DbDydn73L6WR0-fHnKA"
    },
    {
        "domain": ".doubleclick.net",
        "expires": 1646483650.085365,
        "httpOnly": true,
        "name": "IDE",
        "path": "\/",
        "priority": "Medium",
        "sameSite": "None",
        "secure": true,
        "session": false,
        "size": 70,
        "value": "AHWqTUlqh0OPFbGUeGXQqkXebE_Tf9xEs0i7fspXWBfoQHL0p3ooP5Iv-vx7JYmWKsA"
    }],
    "cpu_usage": 634,
    "creative_rendered": true,
    "dialogs": [],
    "dimensions": {
        "height": 250,
        "width": 300
    },
    "dom_content_loaded": 166,
    "has_border": true,
    "has_video": false,
    "iframes": 2,
    "local_storage": [],
    "memory_usage": "11313152",
    "meta": {
        "api_version": "v3.0",
        "cpu": "AMD 16-Core EPYC 7302P",
        "creative_type": "ad_tag",
        "device": "Desktop",
        "language": "en-US",
        "ram": "128GB",
        "scan_duration": "2.809499",
        "server_location": "ams",
        "timestamp": 1612787651,
        "ua": "Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/87.0.4280.88 Safari\/537.36"
    },
    "mobile_friendly": true,
    "network": {
        "load_size": {
            "host_initiated_subload": 0,
            "initial_load": 263515,
            "total": 263515
        },
        "responses": [{
            "bytes": 19175,
            "headers": {
                "cache-control": "private, max-age=900, stale-while-revalidate=3600",
                "content-encoding": "gzip",
                "content-length": "19175",
                "content-type": "text\/javascript",
                "date": "Mon, 08 Feb 2021 12:34:09 GMT",
                "etag": "\"777 \/ 11 of 1000 \/ last-modified: 1612786878\"",
                "expires": "Mon, 08 Feb 2021 12:34:09 GMT",
                "server": "sffe",
                "timing-allow-origin": "*",
                "vary": "Accept-Encoding",
            },
            "is_pixel": false,
            "method": "GET",
            "resource_type": "script",
            "server_ip": "142.250.179.194",
            "ssl": true,
            "ssl_info": {
                "protocol": "TLS 1.3",
                "validFrom": 1611043025,
                "validTo": 1618300624
            },
            "status": 200,
            "status_text": "",
            "timing": 172,
            "url": "https:\/\/securepubads.g.doubleclick.net\/tag\/js\/gpt.js"
        },
        {
            "bytes": 103509,
            "headers": {
                "accept-ranges": "bytes",
                "cache-control": "private, immutable, max-age=31536000",
                "content-encoding": "gzip",
                "content-length": "103509",
                "content-type": "text\/javascript",
                "cross-origin-resource-policy": "cross-origin",
                "date": "Mon, 08 Feb 2021 12:34:09 GMT",
                "expires": "Mon, 08 Feb 2021 12:34:09 GMT",
                "last-modified": "Tue, 02 Feb 2021 09:38:25 GMT",
                "server": "sffe",
                "timing-allow-origin": "*",
                "vary": "Accept-Encoding",
            },
            "is_pixel": false,
            "method": "GET",
            "resource_type": "script",
            "server_ip": "142.250.179.194",
            "ssl": true,
            "ssl_info": {
                "protocol": "TLS 1.3",
                "validFrom": 1611043025,
                "validTo": 1618300624
            },
            "status": 200,
            "status_text": "",
            "timing": 224,
            "url": "https:\/\/securepubads.g.doubleclick.net\/gpt\/pubads_impl_2021020201.js"
        },{
            "..."
        }]
    },
    "job_id": "2af21-de8d9-7cb57-8f014",
    "score": 77,
    "screenshot": {
        "highres": {
            "bytes": 37715,
            "color": "#77b2c1",
            "mime_type": "image\/png",
            "url": "https:\/\/try.cdn.creativeqa.net\/img\/qa-report-983243-aue7bczw9t3v.png"
        },
        "thumbnail": {
            "bytes": 3460,
            "color": "#77b2c1",
            "mime_type": "image\/jpg",
            "url": "https:\/\/try.cdn.creativeqa.net\/img\/qa-report-983243-6gn25mbhxwu9.jpg"
        }
    },
    "ssl": {
        "compliant": true,
        "insecure_urls": []
    },
    "tests": {
        "3pas": {
            "actual": "Google Ad Manager (GAM)",
            "data_type": "string",
            "expected": "Any on list",
            "message": "This is a third-party tag from Google Ad Manager (GAM).",
            "name": "3PAS Vendor",
            "result": "ignored",
            "unit": ""
        },
        "dimensions": {
            "actual": "300x250",
            "data_type": "string",
            "expected": "On acceptable list",
            "message": "This creative has dimensions 300 x 250, which is a standard size.",
            "name": "Ad Dimensions",
            "result": "passed",
            "unit": ""
        },
        "adblock": {
            "actual": true,
            "data_type": "boolean",
            "expected": "false",
            "message": "This tag will likely be blocked by ad blockers. Expect discrepancies when comparing third-party metrics with yours.",
            "name": "Blocked by AdBlock",
            "result": "failed",
            "unit": ""
        },
        "cpu": {
            "actual": 634,
            "data_type": "int",
            "expected": "< 100 ms",
            "message": "This creative uses the CPU for 634 ms. That's quite a lot.",
            "name": "CPU Usage",
            "result": "failed",
            "unit": "ms"
        },
        "blocked_by_heavy_ad_intervention": {
            "actual": false,
            "data_type": "boolean",
            "expected": "< 15 seconds CPU and < 4 MB load size",
            "message": "This ad is not considered heavy, and probably will pass Chrome's Heavy Ad Intervention policy.",
            "name": "Chrome's Heavy Ad Intervention",
            "result": "passed",
            "unit": ""
        },
        "click_tracking_macro": {
            "actual": "",
            "data_type": "string",
            "expected": "Any on list",
            "message": "No click tracking macro has been detected.",
            "name": "Click Tracking Macro",
            "result": "ignored",
            "unit": ""
        },
        "console_warnings": {
            "actual": 0,
            "data_type": "array",
            "expected": "0 warnings",
            "message": "No console warnings have been detected.",
            "name": "Console Warnings",
            "result": "passed",
            "unit": ""
        },
        "cookies": {
            "actual": 2,
            "data_type": "array",
            "expected": "0 cookies",
            "message": "A total of 2 cookies were dropped while loading this ad. Due to global privacy laws, make sure you have user-consent.",
            "name": "Cookies Dropped",
            "result": "failed",
            "unit": ""
        },
        "has_border": {
            "actual": true,
            "data_type": "boolean",
            "expected": "true",
            "message": "This creative has a high-contrasting border.",
            "name": "Creative Border",
            "result": "ignored",
            "unit": ""
        },
        "creative_rendered": {
            "actual": true,
            "data_type": "boolean",
            "expected": "true",
            "message": "The creative was loaded successfully.",
            "name": "Creative Rendered",
            "result": "passed",
            "unit": ""
        },
        "dialogs": {
            "actual": 0,
            "data_type": "boolean",
            "expected": "0 dialogs",
            "message": "No interruptive dialogs have been detected.",
            "name": "Dialogs & Modals",
            "result": "passed",
            "unit": ""
        },
        "host_initiated_subload": {
            "actual": 0,
            "data_type": "int",
            "expected": "< 1048576 bytes",
            "message": "The host-initiated subload is acceptable at 0.00 KB.",
            "name": "Host-initiated Subload",
            "result": "passed",
            "unit": "bytes"
        },
        "iframe_count": {
            "actual": 2,
            "data_type": "int",
            "expected": "<= 3 iframes",
            "message": "This creative uses 2 iframes.",
            "name": "Iframe Count",
            "result": "passed",
            "unit": ""
        },
        "initial_load": {
            "actual": 263515,
            "data_type": "int",
            "expected": "< 1048576 bytes",
            "message": "The initial load size is acceptable at 257.3 KB.",
            "name": "Initial Load",
            "result": "passed",
            "unit": "bytes"
        },
        "js_errors": {
            "actual": 0,
            "data_type": "array",
            "expected": "0 errors",
            "message": "No JavaScript errors have been detected.",
            "name": "JavaScript Errors",
            "result": "passed",
            "unit": ""
        },
        "load_size": {
            "actual": 263515,
            "data_type": "int",
            "expected": "< 1048576 bytes",
            "message": "The load size is acceptable at 257.3 KB.",
            "name": "Load Size (Total)",
            "result": "passed",
            "unit": "bytes"
        },
        "dom_content_loaded": {
            "actual": 166,
            "data_type": "int",
            "expected": "< 1000 ms",
            "message": "The DOMContentLoaded event fired after 166 ms.",
            "name": "Load Speed",
            "result": "passed",
            "unit": "ms"
        },
        "local_storage": {
            "actual": 0,
            "data_type": "int",
            "expected": "0 localStorage objects",
            "message": "This ad doesn't seem to use HTML5 localStorage.",
            "name": "Local Storage",
            "result": "passed",
            "unit": ""
        },
        "memory": {
            "actual": "11313152.0",
            "data_type": "int",
            "expected": "< 5242880 bytes",
            "message": "This creative uses 11 MB of memory. That's quite a lot.",
            "name": "Memory Usage",
            "result": "failed",
            "unit": "bytes"
        },
        "missing_assets": {
            "actual": 0,
            "data_type": "boolean",
            "expected": "No 40x HTTP status codes",
            "message": "All HTTP requests were valid.",
            "name": "Missing Assets",
            "result": "passed",
            "unit": ""
        },
        "mobile_friendly": {
            "actual": true,
            "data_type": "boolean",
            "expected": "true",
            "message": "The creative seems to be responsive on mobile devices.",
            "name": "Mobile Friendly",
            "result": "passed",
            "unit": ""
        },
        "network_requests": {
            "actual": 20,
            "data_type": "int",
            "expected": "<= 15 requests",
            "message": "A total of 20 HTTP requests were made. This has a significant impact on the performance of the creative and the page itself. The IAB suggests a limit of 15 HTTP requests per creative.",
            "name": "Network Requests",
            "result": "failed",
            "unit": ""
        },
        "pixels_fired": {
            "actual": 6,
            "data_type": "int",
            "expected": "< 5 pixels",
            "message": "This creative fires 6 pixels. Keep the amount of pixels at a minimum to improve network performance.",
            "name": "Pixels Fired",
            "result": "failed",
            "unit": ""
        },
        "has_video": {
            "actual": false,
            "data_type": "boolean",
            "expected": "true or false",
            "message": "This ad doesn't seem to play videos.",
            "name": "Plays Video",
            "result": "passed",
            "unit": ""
        },
        "ssl_compliant": {
            "actual": true,
            "data_type": "boolean",
            "expected": "true",
            "message": "All requests are loaded over https, including pixels and images.",
            "name": "SSL-Compliant",
            "result": "passed",
            "unit": ""
        },
        "document_write": {
            "actual": false,
            "data_type": "boolean",
            "expected": "false",
            "message": "This creative doesn't use document.write().",
            "name": "Uses document.write()",
            "result": "passed",
            "unit": ""
        },
        "visual_artifacts": {
            "actual": false,
            "data_type": "boolean",
            "expected": "false",
            "message": "No dimension discrepancies have been detected.",
            "name": "Visual Artifacts",
            "result": "passed",
            "unit": ""
        }
    },
    "uses_document_write": false,
    "visual_artifacts": false,
    "json": {
        "url": "https:\/\/try.cdn.creativeqa.net\/img\/qa-report-983243-txkf9dmzawu7.json"
    }
}

Use this scan to validate ad tags in HTML and/or JavaScript. Add the ad tag as a base64-encoded string to your API request.

Endpoint

POST https://{your_name}.api.creativeqa.net/v3.0/scan/tag

Arguments

data
string, required
The ad tag in base64-encoded format.
server_location
string
The location of the server used to scan the creative:
  • sfo for San Francisco (USA)
  • wdc for Washington DC (USA)
  • ams for Amsterdam (The Netherlands)
  • sgp for Singapore
Defaults to the server the closest to the source from which the API request was made.
timeout
int
Timeout in seconds after which the scan will be canceled.
Range: 10 - 120. Defaults to 60 seconds.

Returns

3pas
string
The name of the third-party ad server, if detected successfully. Remains blank otherwise.
blocked_by_adblock
boolean
Whether or not the tag will likely be blocked by ad blockers.
console
array
All errors and warnings generated while loading the creative.
cookies
array
All cookies that were dropped by the creative, either set via JavaScript or via an HTTP header.
cpu_usage
int
The CPU usage, in milliseconds.
creative_rendered
boolean
Equals true in case something was painted on the screen, false otherwise.
dialogs
array
Any dialog message the creative shows as a pop-up. Generally created by alert() and confirm().
dimensions
array
The detected width and height of the creative.
dom_content_loaded
int
The time it took for the DOMContentLoaded event to fire, in milliseconds.
has_border
boolean
Whether or not the creative has a contrasting border.
has_video
boolean
Whether or not the creative plays video content.
iframes
int
The number of iframes added to the DOM. This should be kept at a minimum to reduce memory usage.
local_storage
array
All key/value pairs stored in window.localStorage.
memory_usage
int
The amount of RAM memory used, in bytes.
meta
array
Meta-data about the scan, like the CPU used, the time it took to complete the scan, the server location, etc.
mobile_friendly
boolean
Whether or not the creative will display fine on a mobile device. Equals true if the creative is responsive or < 300 pixels wide.
network
array
All network requests and their responses, including a full echo of the HTTP headers. Provides SSL certificate information too.
job_id
string
A unique ID assigned to the scan. Store this ID on your own backend to re-fetch result data at a later moment.
score
int
The score, calculated based on the number of failed/passed tests.
screenshot
array
A screenshot of the creative. The url points to a PNG image. The background_color is in hex-format. It generally goes well with the main colors of the screenshot.
ssl
boolean
Whether or not the creative is SSL-compliant. If the creative tries to load assets over http, it will equal false.
tests
array
The most important part of the JSON response: an array of all tests conducted and their results. You can use this array to create your own report.
uses_document_write
boolean
Whether or not the creative uses the JS document.write() function. Synchronous code should be avoided.
visual_artifacts
boolean
If visual artificats have been detected. For example, a 300x250 creative that is actualy 301x251 in size.
json
array
The url contains a link to the JSON result of the scan. Great for manual downloads and inspection.

Retrieve a scan

curl "https://{your_name}.api.creativeqa.net/v3.0/jobs/{job_id}"
  -H "X-ApiKey: {api_key}"
  -X GET

Example response

{
    "3pas": "",
    "blocked_by_adblock": false,
    "..."
}

To retrieve a cached JSON response of a creative you've previously scanned, use the following endpoint. Make sure to use GET as a method. The job_id can be found in the response from a new scan.

Endpoint

GET https://{your_name}.api.creativeqa.net/v3.0/jobs/{job_id}

Returns

response
object
The full JSON response from the original scan.

Software Development Kits

PHP Class (Github)

Here's a PHP Class that makes implementation a bit easier:
https://github.com/CreativeQA/ad-validator-php