Automation

An Automation is a object representation of complex logic to be executed by it's parent object Schedule. Automations enable users to add logical expressions in conjunction with several backend alerting services to run after a given scheduled task. An Automation is comprised of 2 major components:

  1. expressions -> a list of expression objects containing the various parts of a logical expression.
  2. actions -> a list of action objects containing the necessary data to execute the action type.

Automations will accept over 30 different data_types to include all Lighthouse and Yellow lab metrics. For a complete list and description of each available data_type please see Data Types

TIP

Automations are intended for single Schedule use. i.e. one Automation services one Schedule.

Automation object


{
   "id":"f31d8c42-54c9-4e94-9495-2cc1eae4c994",     // uuid specific to Automation
   "expressions":[                                  // an array of expression objects denoting a logical expression
      {
         "joiner":"",                   // should be one of:  "", "and", "or" (first expression joiner is always "")
         "data_type":"test_score",      // the type of data being evaluated (one of: "test_score", "current_average", "seo_delta", "best_practices_delta", "performance_delta", "images_score", "logs", "health")
         "operator":"<=",               // operator used to evaluate expression. One of:  ">=", "<=" 
         "value":"80"                   // the value that "data_type" is being compared to
      },
      {
         "joiner":"or",
         "data_type":"current_average",
         "operator":"<=",
         "value":"75"
      }
   ],
   "actions":[                      // an array of action objects denoting what automated actions to complete when the expressions are evaluated
      {
         "action_type":"slack",     // one of: "slack", "webhook", "phone", "email"
         "url":"",                  // if using webhook: the uri to send the request
         "request":"",              // if using webhook: the request type. One of "POST, "GET"
         "json":"",                 // if using webhook and request == "POST": JSON formatted data to send
         "email":"",                // if using email: the email address to send an alert
         "phone":""                 // if using phone: the number to send a text to e.g +13335558888
      },
      {
         "action_type":"webhook",
         "url":"https://otherwebservice.com/api",
         "request":"POST",
         "json":"{\"test_score\": \"score\"}",
         "email":"",
         "phone":""
      }
   ],
   "user":"example@gmail.com",                          // user denoted by email
   "schedule":"5dd6cc87-5f90-471f-84bd-a1b4c759ea33",   // uuid specific to associated Schedule  
   "time_created":"2021-11-22T20:48:36.153402Z",        // timestamp of Automation creation
   "name":"My Scan Automation"                          // non-unique/non-binding string to help the user remember the automation
}
      

Create or Update Automation

There are two use cases for this endpoint, Creating and Updating Automations.

POST - /automation

# import env vars
SCANERR_API_BASE_URL = os.environ.get('SCANERR_API_BASE_URL')
SCANERR_API_TOKEN = os.environ.get('SCANERR_API_BASE_URL')

# setup configs
url = f'{SCANERR_API_BASE_URL}/automation'
headers = {
    "content-type": "application/json",
    "Authorization" : SCANERR_API_TOKEN
}
data = {
    actions: [
        {
            action_type: "slack", 
            url: "", 
            request: "", 
            json: "", 
            email: "", 
            phone: ""
        },
        {
            action_type: "webhook", 
            url: "https://otherwebservice.com/api", 
            request: "POST", 
            json: "{\"test_score\": \"score\"}" 
            email: "", 
            phone: ""
        }
    ]
    automation_id: ""  # Insert <automation:id> if updating automation
    expressions: [
        {
            joiner: "", 
            data_type: "test_score", 
            operator: "<=", 
            value: "80"
        },
        {
            joiner: "or", 
            data_type: "current_average", 
            operator: "<=", 
            value: "75"
        }
    ]
    

    name: "My Scan Automation"
    schedule_id: "5dd6cc87-5f90-471f-84bd-a1b4c759ea33"
    site_id: "46053956-761b-4ca6-8cec-3be796695d12"
}

# send the request
res = requests.post(
    url=url,
    headers=headers,
    data=json.dumps(data)
)

# retrieve response data
json_response = res.json()
print(json_response)

View Full Output

Output:


{
   "id":"f31d8c42-54c9-4e94-9495-2cc1eae4c994",
   "expressions":[
      {
         "joiner":"",
         "data_type":"test_score",
         "operator":"<=",
         "value":"80"
      },
      {
         "joiner":"or",
         "data_type":"current_average",
         "operator":"<=",
         "value":"75"
      }
   ],
   "actions":[
      {
         "action_type":"slack",
         "url":"",
         "request":"",
         "json":"",
         "email":"",
         "phone":""
      },
      {
         "action_type":"webhook",
         "url":"https://otherwebservice.com/api",
         "request":"POST",
         "json":"{\"test_score\": \"score\"}",
         "email":"",
         "phone":""
      }
   ],
   "user":"example@gmail.com",
   "schedule":"5dd6cc87-5f90-471f-84bd-a1b4c759ea33",
   "time_created":"2021-11-22T20:48:36.153402Z",
   "name":"My Scan Automation"
}

Retrieve an Automation

This endpoint returns a single Automation object and is useful as a simple "detailed view" of the automation.

GET - /automation/<automation:id>

import requests, os

# import env vars
SCANERR_API_BASE_URL = os.environ.get('SCANERR_API_BASE_URL')
SCANERR_API_TOKEN = os.environ.get('SCANERR_API_BASE_URL')

# setup configs
url = f'{BASE_URL}/automation/<automation:id>'
headers = {
    "content-type": "application/json",
    "Authorization" : SCANERR_API_TOKEN
}

# send the request
res = requests.get(
    url=url, 
    headers=headers, 
)

# retrieve response data
json_response = res.json()
print(json_response)

View Full Output

Output:


{
   "id":"f31d8c42-54c9-4e94-9495-2cc1eae4c994",
   "expressions":[
      {
         "joiner":"",
         "data_type":"test_score",
         "operator":"<=",
         "value":"80"
      },
      {
         "joiner":"or",
         "data_type":"current_average",
         "operator":"<=",
         "value":"75"
      }
   ],
   "actions":[
      {
         "action_type":"slack",
         "url":"",
         "request":"",
         "json":"",
         "email":"",
         "phone":""
      },
      {
         "action_type":"webhook",
         "url":"https://otherwebservice.com/api",
         "request":"POST",
         "json":"{\"test_score\": \"score\"}",
         "email":"",
         "phone":""
      }
   ],
   "user":"example@gmail.com",
   "schedule":"5dd6cc87-5f90-471f-84bd-a1b4c759ea33",
   "time_created":"2021-11-22T20:48:36.153402Z",
   "name":"My Scan Automation"
}

Retrieve many Automations

This endpoint returns a paginated response with all Automation objects filtered by your account and ordered by time_created. This endpoint is useful when needing to displaying your sites in a table view for example. The limit parameter specifies the total number of objects you want returned per "group" (we recomend keeping this under 10 for best performance). The offset parameter specfies which "group" to return. For example, limit=10&offset=10 in a total dataset of 30 objects would return 10 automations in range automation #10 - automation #20.

GET - /automation?limit=10&offset=0

import requests, os

# import env vars
SCANERR_API_BASE_URL = os.environ.get('SCANERR_API_BASE_URL')
SCANERR_API_TOKEN = os.environ.get('SCANERR_API_BASE_URL')

# setup configs
url = f'{BASE_URL}/automation?limit=10&offset=0'
headers = {
    "content-type": "application/json",
    "Authorization" : SCANERR_API_TOKEN
}

# send the request
res = requests.get(
    url=url, 
    headers=headers, 
)

# retrieve response data
json_response = res.json()
print(json_response)

View Full Output

Output:

{
   "count":30,
   "next":"https://api.scanerr.io/v1/ops/automation?limit=10&offset=20",
   "previous":"https://api.scanerr.io/v1/ops/automation?limit=10&offset=10",
   "results":[
        {
            "id":"f31d8c42-54c9-4e94-9495-2cc1eae4c994",
            "expressions":[
                {
                    "joiner":"",
                    "data_type":"test_score",
                    "operator":"<=",
                    "value":"80"
                },
                {
                    "joiner":"or",
                    "data_type":"current_average",
                    "operator":"<=",
                    "value":"75"
                }
            ],
            "actions":[
                {
                    "action_type":"slack",
                    "url":"",
                    "request":"",
                    "json":"",
                    "email":"",
                    "phone":""
                },
                {
                    "action_type":"webhook",
                    "url":"https://otherwebservice.com/api",
                    "request":"POST",
                    "json":"{\"test_score\": \"score\"}",
                    "email":"",
                    "phone":""
                }
            ],
            "user":"example@gmail.com",
            "schedule":"5dd6cc87-5f90-471f-84bd-a1b4c759ea33",
            "time_created":"2021-11-22T20:48:36.153402Z",
            "name":"My Scan Automation"
        },
        {
            "id":"f31d8c42-54c9-4e94-9495-2cc1eae4c994",
            "expressions":[
                {
                    "joiner":"",
                    "data_type":"test_score",
                    "operator":"<=",
                    "value":"80"
                },
                {
                    "joiner":"or",
                    "data_type":"current_average",
                    "operator":"<=",
                    "value":"75"
                }
            ],
            "actions":[
                {
                    "action_type":"phone",
                    "url":"",
                    "request":"",
                    "json":"",
                    "email":"",
                    "phone":"+13335558888"
                },
                {
                    "action_type":"webhook",
                    "url":"https://otherwebservice.com/api",
                    "request":"POST",
                    "json":"{\"test_score\": \"score\"}",
                    "email":"",
                    "phone":""
                }
            ],
            "user":"example@gmail.com",
            "schedule":"5dd6cc87-5f90-471f-84bd-a1b4c759ea33",
            "time_created":"2021-11-22T20:48:36.153402Z",
            "name":"My Other Scan Automation"
        }

      ### SHORTENED FOR DISPLAY PURPOSES ###
   ]
}

Delete an Automation

DANGER

Please use caution with this endpoint as it is irreversible.

DELETE - /automation/<automation:id>

import requests, os

# import env vars
SCANERR_API_BASE_URL = os.environ.get('SCANERR_API_BASE_URL')
SCANERR_API_TOKEN = os.environ.get('SCANERR_API_BASE_URL')

# setup configs
url = f'{BASE_URL}/automation/<automation:id>'
headers = {
    "content-type": "application/json",
    "Authorization" : SCANERR_API_TOKEN
}

# send the request
res = requests.delete(
    url=url, 
    headers=headers, 
)

# retrieve response data
json_response = res.json()
print(json_response)

View Full Output

Output:

    {
        "message": "Automation has been deleted"
    }

Data Types

Below is a verbose list of all available data type names, a description of the data, and which task_types can utilize them.


Name (string)DescriptionTask
healthCalculated health score from that ScanScan
logsTotal number of error logs found in that ScanScan
lighthouse_averageAverage of all Lighthouse scores for that ScanScan
seoSEO score for that ScanScan
performancePerfomance score for that ScanScan
best_practicesBest Practices score for that ScanScan
accessibilityAccessibility score for that ScanScan
pwaPWA score for that ScanScan
cruxCRUX score for that ScanScan
yellowlab_averageAverage of all Yellow Lab scores for that ScanScan
pageWeightPage Weight score for that ScanScan
imagesRequests score for that ScanScan
domComplexityDOM Complexity score for that ScanScan
javascriptComplexityJS Complexity score for that ScanScan
badJavascriptBad JS score for that ScanScan
jQueryjQuery score for that ScanScan
cssComplexityCSS Complexity score for that ScanScan
badCSSBad CSS score for that ScanScan
fontsFonts score for that ScanScan
serverConfigServer Config score for that ScanScan
test_scoreCalculated test score from that TestTest
current_healthCalculated health score from second ScanTest
current_lighthouse_averageAverage of all Lighthouse scores from second ScanTest
seo_deltaDifference in SEO scoresTest
performance_deltaDifference in Perfomance scoresTest
best_practice_deltasDifference in Best Practices scoreTest
accessibility_deltaDifference in Accessibility scoreTest
pwa_deltaDifference in PWA scoresTest
crux_deltaDifference in CRUX scoresTest
current_yellowlab_averageDifference in Average of all Yellow Lab scores from second ScanTest
pageWeight_deltaDifference in Page Weight scoreTest
images_deltaDifference in Requests scoreTest
domComplexity_deltaDifference in DOM Complexity scoreTest
javascriptComplexity_deltaDifference in JS Complexity scoreTest
badJavascript_deltaDifference in Bad JS scoreTest
jQuery_deltaDifference in jQuery scoreTest
cssComplexity_deltaDifference in CSS Complexity scoreTest
badCSS_deltaDifference in Bad CSS scoreTest
fonts_deltaDifference in Fonts scoreTest
serverConfig_deltaDifference in Server Config scoreTest
avg_image_scoreThe average score of all images compared in that TestTest
image_scoresAn array of image scores found in that TestTest
Last Updated:
Contributors: landon, Landon