IVR Integration

Why move voice traffic to messaging?

There are scenarios where it is beneficial for your business and customers to move inquiries from voice to a messaging channel:

  • Long voice wait times
  • Automate data collection and self service
  • The inquiry type requires a digital exchange (e.g. photo)

Benefits for your business

  • Increased efficiency

    • Empower your agents to handle multiple conversations concurrently
    • Confirm the inquiry type and route to the right team the first time
    • Automate upfront data collection of basic account information
    • Prioritize high value customers and urgent issues
    • Fully automate common inquiries
  • Improved CSAT

    • Free your agents time with partial or full automation
    • Strengthen customer relationships on channels used for friends and family
    • Promote consistency of service with snippets, auto suggest and coaching
    • Increase feedback with in thread surveys

Benefits for your customers

  • Provides peace of mind that their inquiry will be addressed
  • Allows the customer to multi task and communicate at their desired pace
  • Opens up a direct avenue for them to request help whenever they need it
  • Allows them to self serve when appropriate

Channel considerations

Quiq supports a number of channels that can help reduce your voice call volume.

Facebook and Instagram ℹ️

FB and IG social channels are not directly intended to help you deflect voice call volume. However, offering support on these channels provides another avenue for your customers to get help from your business.

Apple Messages for Business

Messaging a customer directly using their phone number will send a message if the end user has previously engaged on the channel and you have associated their phone number with a previous conversation. Apple also offers a Chat Suggest feature that allows customers to connect via messaging before ever reaching your IVR system. Please contact your Quiq Customer Success manager to learn more about Apple Messages for Business.

Google Business Messages

Messaging a customer directly using their phone number will send a message if the end user has previously engaged on the channel and you have associated their phone number with a previous conversation. Google also offers a number of entry points that allow customers to connect via messaging before ever reaching your IVR system. Please contact your Quiq Customer Success manager to learn more about Google Business Messages.

WhatsApp

WhatsApp allows you to message a customer directly using their phone number. Your business may prefer WhatsApp over SMS to provide a richer messaging experience and avoid the higher costs associated with SMS conversations.

If your business prefers WhatsApp, it is important to note:

SMS

SMS allows you to message a customer directly using their phone number. Your IVR flow should have an opt-in and you can review our SMS Compliance Considerations for more information.

API Integration

Your IVR system will need to make an API call to Quiq at the appropriate time during a call flow. You can pass information about the call inquiry to Quiq via messages and field data. You can also configure topics and conversation rules to prioritize and route conversations to the right bot or agent team.

Authentication

An IVR integration with Quiq is designed for server to server communication. To make requests to the Quiq API from your application, you will pass your credentials using the Basic HTTP Authentication Scheme RFC 7617. To get an API key and secret, an admin of your Quiq site will:

  • Navigate to Admin > Bots
  • Give your bot a name to identify the purpose of the integration
  • Do not assign any roles and Save
  • Select Custom Bot and Save
  • Add a New API Key
  • Your secret will only be available upon provisioning
  • Store your credentials securely

Admin users can also provision API credentials associated with their Quiq user. However, using a bot to provision integration credentials allows your Quiq admins to inventory integration credentials and manage them accordingly. The Quiq admin who provisioned the bot credentials is recorded alongside the bot API key entry in the Quiq UI.

Notify or Start Conversation API?

There are two possible APIs you will want to consider when moving voice calls to messaging:

Notify API

The notify API will prevent conversations from getting created and assigned until the customer responds. If your business prefers WhatsApp, agents will not be allowed to message the customer until they engage. Using the `notify' API prevents agents from getting assigned conversations they cannot action.

Additionally, you may want to use the notify API if your use case requires the customer to be prepared for assistance. Here are a couple examples when you would use the notify API:

  • We're sorry your product arrived damaged. Your customer service representative will need an image to assist. When you are ready to share the image, just text "ready" and an agent will be with you shortly.

  • We're sorry there is a problem setting up your internet service. Your customer service representative will need you to be with your equipment. When you are with your equipment, just text "ready" and an agent will be with you shortly.

Example integration

const https = require('https'); // built in Node.js module     

// update your environment                                                                                                                                                                                                                           
const {                                                                                                                              |
  Q_KEY,                                                                                                               |
  Q_SECRET,                                                                                                         |
  Q_SUBDOMAIN,                                                                                                       |
  Q_CONTACT_POINT,
  APPLE_BUSINESS_ID,
  GOOGLE_BUSINESS_ID     
  WHATSAPP_BUSINESS_ID     
} = process.env;

const CHANNEL_PRECEDENCE = [{
  platform: 'AppleMessages',
  tenantHandle: APPLE_BUSINESS_ID
}, {
  platform: 'GoogleMessages',
  tenantHandle: GOOGLE_BUSINESS_ID
}, {
  platform: "WhatsApp",
  tenantHandle: WHATSAPP_BUSINESS_ID
}, {
  platform: 'SMS'
}];

// full API docs - https://developers.goquiq.com/api/docs#operation/Notify
const notify = props => new Promise((resolve, reject) => {
  let {
    phoneNumber, // required - end user E.164 phone number                                                                                                                                                                                                                                                                                                                                                                                   
    topic, // optional - https://knowledge.quiq.com/docs/topic-settings                                                                                                                                                                                                                                                                                                                                                                      
    conversationFields = {}, // optional - https://knowledge.quiq.com/docs/custom-fields#conversation-fields                                                                                                                                                                                                                                                                                                                                 
    customerFields = {}, // optional - https://knowledge.quiq.com/docs/custom-fields#customer-fields                                                                                                                                                                                                                                                                                                                                         
  } = props;

  // structure our field update directives                                                                                                                                                                                                                                                                                                                                                                                  
  conversationFields = Object.keys(conversationFields).map(k => {
    return { field: `schema.conversation.custom.${k}`, value: conversationFields[k] };
  });
  customerFields = Object.keys(customerFields).map(k => {
    return { field: `schema.conversation.customer.custom.${k}`, value: customerFields[k] };
  });
  const fieldUpdates = conversationFields.concat(customerFields);

  const options = {
    hostname: `${Q_SUBDOMAIN}.goquiq.com`,
    path: `/api/v1/messaging/notify`,
    method: 'POST',
    port: 443,
    headers: {
      'Authorization': 'Basic ' + new Buffer.from(Q_KEY+':'+Q_SECRET).toString('base64'),
      'Content-Type': 'application/json'
    }
  };

  const body = {
    contactPoint: Q_CONTACT_POINT,
    notifications: [{
      searchInfo: {
        phoneNumber,
        searchId: phoneNumber
      },
      precedence: CHANNEL_PRECEDENCE,
      messageMap: {
        default: {
          text: "We're sorry your product arrived damaged. Your customer service representative will need an image to assist. When you are ready to share the image, just text "ready" and an agent will be with you shortly.",                                                                                                                                                                                                                                                                                                                                
          directives: { fieldUpdates }
        },
      }
    }]
  };

  // set the topic if passed                                                                                                                                                                                                                                                                                                                                                                                                                   
  if (topic) body.topic = topic;

  // make the request to the Quiq API
  const req = https.request(options, res => {
    let rawData = '';
    res.on('data', chunk => {
      rawData += chunk;
    });

    res.on('end', () => {
      try {
        const { status = 200 } = JSON.parse(rawData);
        if (status !== 200) throw rawData;
        resolve(JSON.parse(rawData));
      } catch (err) {
        reject(new Error(err));
      }
    });
  });
  req.on('error', err => {
    reject(new Error(err));
  });
  req.write(JSON.stringify(body));
  req.end();
});

module.exports = { notify };

Start Conversation API

The start-conversation API allows you to import an initial message from the customer and send a system message to customer. The conversation will start immediately and you can also set custom fields through the API to achieve the desired routing behavior based on your conversation rules.

Example integration

const https = require('https'); // built in Node.js module

// update these with your environment configuration                                                                                                                                                                                                                           
const {                                                                                                                              |
  Q_KEY,                                                                                                               |
  Q_SECRET,                                                                                                         |
  Q_SUBDOMAIN,                                                                                                       |
  Q_CONTACT_POINT,
  APPLE_BUSINESS_ID,
  GOOGLE_BUSINESS_ID
} = process.env;

const CHANNEL_PRECEDENCE = [{
  platform: 'AppleMessages',
  tenantHandle: APPLE_BUSINESS_ID
}, {
  platform: 'GoogleMessages',
  tenantHandle: GOOGLE_BUSINESS_ID
}, {
  platform: 'SMS'
}];

// full API docs - https://developers.goquiq.com/api/docs#operation/Start%20a%20conversation%20(cross%20platform)
const startConvo = props => new Promise((resolve, reject) => {
  let {
    phoneNumber, // required - end user E.164 phone number                                                                                                                                                                                                                                                                                                                                                                                   
    conversationFields = {}, // optional - https://knowledge.quiq.com/docs/custom-fields#conversation-fields                                                                                                                                                                                                                                                                                                                                 
    customerFields = {}, // optional - https://knowledge.quiq.com/docs/custom-fields#customer-fields                                                                                                                                                                                                                                                                                                                                         
  } = props;

  // structure field update directives                                                                                                                                                                                                                                                                                                                                                                                                         
  conversationFields = Object.keys(conversationFields).map(k => {
    return { field: `schema.conversation.custom.${k}`, value: conversationFields[k] };
  });
  customerFields = Object.keys(customerFields).map(k => {
    return { field: `schema.conversation.customer.custom.${k}`, value: customerFields[k] };
  });
  const fields = conversationFields.concat(customerFields);

  const options = {
    hostname: `${Q_SUBDOMAIN}.goquiq.com`,
    path: `/api/v1/messaging/start-conversation`,
    method: 'POST',
    port: 443,
    headers: {
      'Authorization': 'Basic ' + new Buffer.from(Q_KEY+':'+Q_SECRET).toString('base64'),
      'Content-Type': 'application/json'
    }
  };

  const body = {
    contactPoint: Q_CONTACT_POINT,
    searchInfo: {
      phoneNumber,
      searchId: phoneNumber
    },
    precedence: CHANNEL_PRECEDENCE,
    messageMaps: [{
      // an imported message that helps the agent and Quiq Compose get started (NOT sent to customer)                                                                                                                                                                                                                                                                                                                                      
      authorType: 'Customer',
      imported: true,
      default: {
        text: `IVR customer needs help with ${conversationFields.reasonForInquiry}`,
      }
    }, {
      // a message sent to the customer to acknowledge the IVR to messaging switch                                                                                                                                                                                                                                                                                                                                      
      // alternatively, you can configure conversational rules or a bot to provide dynamic messaging based on context (estimated wait time, HOOP, etc)                                                                                                                                                                                                                                                                                   
      authorType: 'System',
      default: {
        text: `Thanks for contacting us today. An agent will be with you as soon as possible.`,
      }
    }],
    fields
  };

  // make the request to the Quiq API
  const req = https.request(options, res => {
    let rawData = '';
    res.on('data', chunk => {
      rawData += chunk;
    });

    res.on('end', async () => {
      try {
        const { status = 200 } = JSON.parse(rawData);
        if (status !== 200) throw rawData;
        resolve(JSON.parse(rawData));
      } catch (err) {
        // do something useful with your errors                                                                                                                                                                                                                                                                                                                                                                                          
        reject(new Error(err));
      }
    });
  });
  req.on('error', err => {
    reject(new Error(err));
  });
  req.write(JSON.stringify(body));
  req.end();
});

module.exports = { startConvo };