Structure of the results

Structure of normalizedDataset output

Both normalizeGaResult() and normalizeAtiResult() functions are constructed to simplify manipulation with the data and to prepare the data for transformation into a table (using the table() function). They make the structure of the data more compact and thus it is clearer to extract the values from the data.

The input of the normalizeGaResult() or normalizeAtiResult() functions is the output for a single query of a request (for more detail of the use of these functions, refer to section Test logic of the test). This creates normalized dataset with an Array of data which contains key-value pairs for all dimensions and metrics.

normalizedDataset [Array]

  • row 1 [Object]
    • contains key: value pairs for all dimensions and metrics
  • ...

Below is an example of the normalized dataset for a Google Analytics query with one dimension ('ga:hostname') and two metrics ('ga:sessions', 'ga:users'). Notice how the 'ga:' prefixes are omitted in normalized data for clearer overview.

[
   {
     "hostname": "hostname1.cz",
     "sessions": 2000,
     "users": 1000
   },
   {
     "hostname": "hostname2.cz",
     "sessions": 1500,
     "users": 750
   },
   {
     "hostname": "hostname3.cz",
     "sessions": 220,
     "users": 110
   }
]

If you want to calculate the Session per user ratio for the hostname with the highest number of sessions, you can extract the data from the first row of observations (hostname = 'hostname1.cz') as the hostnames in this result are ordered by the number of sessions in a decreasing way. In particular, for Google Analytics data you can use the following calculation:

const hostnameSessions = normalizeGaResult(results['hostnameSessions'][0])
const maxHostname_sessions = +hostnameSessions[0]['sessions']
const maxHostname_users = +hostnameSessions[0]['users']
const maxHostname_sessionUserRatio = maxHostname_sessions / maxHostname_users
Note:
The plus sign added to the extraction of numbers from the results is necessary if you want to manipulate with the extracted values as with numbers. The results are stored as strings and by adding a plus sign in front of the value extraction, the value is converted to a number.

Structure of summarizedResult output

The summarizedResult is the output of the functions summarizeGaResult() or summarizeAtiResult(). The summarizeGaResult() function extracts the summary statistics from the query output data from Google Analytics. For Piano Analytics (formerly AT Internet) data the summary is just calculated from the extracted data.

Note:
This means that while the result of summarizeGaResult() shows the summary of the full data irrespective of the part loaded in a single call, for Piano Analytics data the summary provided by summarizeAtiResult() only sums the loaded rows.

The result is an Object with summary the sum of all values (called 'total'), maximum and minimum value (called 'maximum' and 'minimum') and the type (marked as 'type') for every metric included in the data.. For Google Analytics data the possible types of metrics include: INTEGER, FLOAT, CURRENCY, PERCENT, and TIME.

summarizedResult [Object]

  • metric 1 [Object]
    • total = sum for given metric
    • minimum = minimum for given metric
    • maximum = maximum for given metric
    • type = type of metric
  • ...

Below you can compare the summarized results for the same data as the normalizedDataset in the previous subsection, i.e. a query with one dimension ('ga:hostname') and two metrics ('ga:sessions', 'ga:users'). Again, you can notice how the 'ga:' prefixes are omitted in summarized data for clearer overview.

{
  "sessions": {
    "total": 123456,
    "minimum": 0,
    "maximum": 3300,
    "type": "INTEGER"
  },
  "users": {
    "total": 65432,
    "minimum": 1,
    "maximum": 1500,
    "type": "INTEGER"
  }
}

To extract the total number of users and maximum number of sessions you can write:

const hostnameSessionsSummary = summarizeGaResult(results['hostnameSessions'][0])
const totalUsers = +hostnameSessionsSummary['users']['total']
const maxSessions = +hostnameSessionsSummary['sessions']['maximum']

Structure of non-transformed input data

Structure of non-transformed Google Analytics results

While it is recommended to use the Waaila function normalizeGaResult() to transform the Google Analytics data to the normalizedDataset format, we also provide information about the structure of the data before the transformation in case you wanted to use the raw data.

The output of requests to Google Analytics has the following structure from which the way to access the data is derived. When you run a test, all results for a given Query logic are combined within an Array results. For each request within this Query logic you can access the output by subsetting the results using the ID of the request. For a request with id "sessions" you can do this by results['sessions'].

In the Array of outputs for a given request there are results for each query of given request stored as Objects. The query results contain two parts: column header with names of dimensions and metrics (marked as columnHeader) and the main data. Therefore, to access the main data you need to follow the following structure. You can assign the resulting data of each query within each request to a dataset variable so that you can easier work with it. Here is an example for a request containing data on sessions with ID "sessions".

const sessionsData = results['sessions'][0].data;`

results [Array]

  • request 1 results (subset by request 1 ID) [Array]
    • query 1 results (subset by 0) [Object]
      • columnHeader [Object]
      • data [Object]
    • query 2 results (subset by 1) [Object] - …
  • request 2 results (subset by request 2 ID) [Array]
    • query 1 results (subset by 0) [Object]
      • columnHeader [Object]
        • data [Object]

Next, we describe the structure of the main data that we have stored within a variable. The main part of the data is the Array rows. The Array rows contains an Object with values of dimensions stored in data.rows[0].dimensions and values of metrics stored in data.rows[0].metrics[0].values. Within these values the dimensions and metrics are not stored under names but in the order as they were queried and as they are written in the columnHeader. Therefore, when you access the data, you need to keep in mind what is the position of the metric that you need to use. This procedure can be greatly improved and simplified when you use the gaResultToJson() function which allows you to access the metrics values directly by the metrics’ names.

Apart from the main rows with data, there are three aggregated Arrays with totals, minimums and maximums and lastly there is the information on the number of rows. The aggregated Arrays have the same structure as the metrics Array within rows.

We use the previous example with sessions defined as the results of the first query in the request with id "sessions". This data is ordered descending by sessions, so to get the maximum sessions maxSessions, you can either find it in the maximums or in the first row of the metrics. We use the later, to show the parallel with accessing the corresponding hostname (the former can be seen in the Use case 1). Therefore, the values of metrics on the first row are in sessions.rows[0].metrics[0].values and the maxSessions is defined as the first value of it by subsetting it with [0]. The plus in front of the expression converts the content to a numeric value (as the JSON is primarily stored in strings). The corresponding hostname is the first dimension [0] on the first row if dimensions sessions.rows[0].dimensions. Lastly, all totals are within sessions.totals[0].values and as the sessions are the first metric, it is accessed by subsetting it with [0]. All these four steps, defining the sessions data and accessing the three values, are stated below:

const sessionsData = results['sessions'][0].data
const maxSessions = +sessionsData.rows[0].metrics[0].values[0]
const hostName = sessionsData.rows[0].dimensions[0]
const totalSessions = +sessionsData.totals[0].values[0]

data [Object]

  • rows [Array]
    • row 1 (subset by 0) [Object]
    • dimensions [Array] – combination of dimensions’ values
    • metrics [Array]
      • first and only content for metrics (subset by 0) [Object]
        • values [Array] – values of metrics for given combination of dimensions
    • row 2 (subset by 1) [Object]
  • totals [Array] - first and only content for total (subset by 0) [Object] - values [Array] – total values of metrics
  • minimums [Array] - first and only content for minimum (subset by 0) [Object] - values [Array] – minimum values of metrics
  • maximums [Array] - first and only content for maximum (subset by 0) [Object] - values [Array] – maximum values of metrics
  • rowCount – total number of rows in the row Array (as an integer)

Structure of non-transformed Piano Analytics (formerly AT Internet) results

While it is recommended to use the Waaila function normalizeAtiResult() to transform the Piano Analytics (formerly AT Internet) data to the normalizedDataset format, we also provide information about the structure of the data before the transformation in case you wanted to use the raw data. These data are in a similar format as the normalizedDataset and additionally, they provide some further information about the columns used. To compare the structure, we provide first an example of original data from Piano Analytics and below the normalizedDataset using the same data - for visits and count of distinct visitors on domains.

Original Piano Analytics data for a single query:

{
  "DataFeed": {
    "Columns": [
      {
        "Category": "Dimension",
        "Name": "site_domain",
        "Type": "String",
        "CustomerType": "String",
        "Label": "Site.domain",
        "Description": "",
        "Filterable": true
      },
      {
        "Category": "Metric",
        "Name": "m_visits",
        "Type": "Integer",
        "CustomerType": "Integer",
        "Label": "Visits",
        "Description": "A visit is defined as a set of events that occured on your site (\"onsite\" event) by the same visitor. If no event is measured during a defined period of time (usually 30 minutes), the visit ends.",
        "Pie": true,
        "Precision": 0,
        "Filterable": true,
        "Summable": true
      },
      {
        "Category": "Metric",
        "Name": "m_unique_visitors",
        "Type": "Integer",
        "CustomerType": "Integer",
        "Label": "Visitors",
        "Description": "Number of visitors (each people recognized mainly with a cookie and who has made at least 1 visit). These visitors are distincts on the period.",
        "Pie": false,
        "Precision": 0,
        "Filterable": true,
        "Summable": false
      }
    ],
    "Rows": [
      {
        "site_domain": "hostname1.cz",
        "m_unique_visitors": 110000,
        "m_visits": 96000
      },
      {
        "site_domain": "hostname2.cz",
        "m_unique_visitors": 80000,
        "m_visits": 65000
      },
      {
        "site_domain": "hostname3.cz",
        "m_unique_visitors": 10000,
        "m_visits": 7500
      }
    ],
    "Context": {
      "Periods": [
        {
          "Value": "2020-09-01"
        }
      ]
    }
  }
}

normalizedDataset for the same query (note the use of labels for column names in the normalizedDataset):

[
    {
        "Site.domain": "hostname1.cz",
        "Visits": 110000,
        "Visitors": 96000
    },
    {
        "Site.domain": "hostname2.cz",
        "Visits": 80000,
        "Visitors": 65000
    },
    {
        "Site.domain": "hostname3.cz",
        "Visits": 10000,
        "Visitors": 7500
    }
]