Extract Survey Responses And Analytics

Overview

Medallia Experience Cloud is the fabric over which customer and employee experiences can be captured, organized, analyzed, and actioned. Raw data can be extracted from Experience Cloud for archiving in data warehouses, or aggregated analytics can be run on the data and results pulled out and used. Medallia Query API is the engine powering these use cases.

In this guide, we will show how to extract survey responses using Medallia Query API. Read the Query API overview to familiarize yourself with its principles.

Example Use Cases

  • Publish company NPS on the corporate intranet by periodically querying for the latest value.
  • Pull data from Medallia in a stream to a corporate data warehouse.

API Used

Authentication

Query API uses OAuth 2.0 for authentication. For all the examples below, we use ${TOKEN} to refer to the OAuth 2.0 access token granted. See Authentication to learn how to obtain your token.

Hello, Me!

The first query is to the me object. It is the most basic query, and a successful response means you have worked through most of the underlying mechanics.

Let’s make our first query:

query {
  me {
    roles {
      id
      name
    }
  }
}
{}

Now let's translate that to a curl request/response:

curl \
    -X POST \
    -H 'Authorization: Bearer ${TOKEN}' \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    --data-binary '{
        "query": "query helloWorld { me { roles { id name } } }",
        "variables": {}
    }' \
    ${API_GATEWAY}/data/v0/query

{
  "data": {
    "me": {
      "roles": [
        {
          "id": "1234",
          "name": "Query API"
        }
      ]
    }
  }
}
POST /data/v0/query HTTP/1.1
Host: ${API_GATEWAY}
Authorization: Bearer ${TOKEN}
Content-Type: application/json
Accept: application/json

{
  "query": "query helloWorld { me { roles { id name } } }",
  "variables": {}
}
HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": {
    "me": {
      "roles": [
        {
          "id": "1234",
          "name": "Query API"
        }
      ]
    }
  }
}

And with that, we have made our first Query API call. The server recognizes our authentication token and has given us some basic data about the role with which our account is associated.

From this point forward, we omit the curl command for the sake of brevity.

Extracting Survey Responses

Survey responses are extracted from MEC in several different ways:

  • Regular and periodic batch exports over SFTP, S3, or similar
  • Near-real-time HTTP webhook pushes
  • Demand-based HTTP pulls

A batch export is most efficient, as Medallia can deliver gigabytes of data at a time with little operational overhead on your IT systems to pick up and consume the file(s).

A webhook allows for integrating Medallia into quick control loops where low latency after a response is submitted is important.

A demand-based HTTP pull, using Query API, is sometimes the tool of choice for an IT department that has migrated to an API-first approach. Let’s explore this path further.

query getSurveyTakerContactDetails(
    $filter: Filter
) {
  feedback(
      filter: $filter
  ) {
    nodes {
      id
      email: fieldData(fieldId: "e_email") {
        values
      }
      name: fieldData(fieldId: "a_fullname") {
        values
      }
    }
    totalCount
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
{
  "filter": null
}
{
  "data": {
    "feedback": {
      "nodes": [
        {
          "id": "12827260",
          "email": { "values": ["[email protected]"] },
          "name": { "values": ["John Patterson"] }
        },
        {
          "id": "12827258"
          "email": { "values": ["[email protected]"] },
          "name": { "values": ["Mary Jackson"] }
        },
        ...
      ],
      "totalCount": 4831376,
      "pageInfo": {
        "hasNextPage": true,
        "endCursor": "xWSJSCIGh9+8WBydu4cOW5xdK9Q"
      }
    }
  }
}

First, we’ve added a variable. The $filter parameter can be used to limit the search to a subset of records. Filtering is composed of an aggregate operation (and, or, not, etc.) with a nesting of other aggregate operations or field-specific operations.

Second, the data we’re getting back is much richer now! We asked the feedback endpoint to give us each record’s id, the totalCount of records that matched, and the pageInfo needed to make the next query in the pagination.

📘

Naming queries is optional but recommended

GraphQL does not require queries to be named, but it is considered a best practice. In the example above, we used the name getSurveyTakerContactDetails as a way to document the code's purpose for future programmers.

Historical Data

When the data you want to query is available in Experience Cloud for more than 24 hours, you can make queries similar to what’s shown above.

Streaming Data

When the data you want to query is more immediate and effectively a pull-based stream, a few other considerations are needed.

📘

Experience Cloud is powered by a proprietary OLAP engine. That OLAP has the eventual consistency properties of any large-scale distributed database architecture. In most cases, this eventual consistency is on the order of a few seconds to a few minutes.

When streaming data from Experience Cloud using Query API, we need to modify queries to track survey ID and initial finish dates to ensure that no survey responses are missed.

Medallia has published medallia/query-api-data-extract as an example of performing a streaming operation. While we won’t get into the details in this guide, below is GraphQL from that as an example of a more complex query structure:

query stream(
    $numRecordsPerRequest: Int!,
    $surveyId: ID!,
    $initialFinishDate: ID!,
    $startSurveyId: String!,
    $startTime: String!,
    $endTime: String!
) {
  feedback(
      first: $numRecordsPerRequest
      orderBy: [
        { direction: ASC  fieldId: $initialFinishDate }
        { direction: ASC  fieldId: $surveyId }
      ]
      filter: { and: [
        { fieldIds: [ $initialFinishDate ], lt: $endTime }
        { or: [
          { fieldIds: [ $initialFinishDate ], gt: $startTime }
          { and: [
            { fieldIds: [ $initialFinishDate ], gte: $startTime }
            { fieldIds: [ $surveyId ], gt: $startSurveyId }
          ] }
        ] }
      ] }
  ) {
    totalCount
    nodes {
      id
      initialFinishDate: fieldData(fieldId: $initialFinishDate) {
        Values
      }
    }
  }
}

Conclusion

We showed you how to use Medallia Query API to make basic queries and extract survey responses. These fundamentals can be used to build complex integrations and further explore other Query API capabilities.

Query API is one mechanism for extracting data from Experience Cloud. File-based exports and webhooks may be alternatives to consider for your integration needs.

Medallia has published a Java-based reference implementation at medallia/query-api-data-extract that provides a scheduled service that streams data from Experience Cloud using Query API.