Expand Minimize

Creating Screen Pop Windows Using Lync 2010 SDK

Summary:   This article describes how to create a screen pop window that loads information from a Bing search that is based on the caller’s phone number.

In contact centers and other organizations that receive frequent calls from customers, it is important to handle as many requests as possible on the first contact, and to handle them as efficiently as possible. This helps minimize costs while keeping customers satisfied. To help agents handle requests quickly, it is common to have a window with information relevant to the call automatically load on the agent’s screen when a call arrives. This window is usually called a screen-population (screen pop) because the screen is populated with customer information.

There are several kinds of screen pops. In some instances, a new window opens automatically with customer details that are relevant to the call. In other examples, the caller’s record is automatically loaded in a customer relationship management (CRM) or enterprise resource planning (ERP) client on the agent’s desktop.

As organizations deploy Microsoft Lync Server 2010, they often want to know how to enable screen pop functionality for customer-facing staff. Rather than force every organization to use a single, built-in screen pop feature, Lync Server 2010 provides a .NET client API which makes it easy for organizations to create their own screen pop applications or integrate existing pops with Microsoft Lync 2010, with minimal development effort.

This article describes with a basic sample application how to create a screen pop that loads information from a Bing search that is based on the caller’s phone number.

To use the sample code in this article, you must install the Microsoft Lync 2010 SDK. The Bing search component of the sample requires a Bing AppID. You can create an AppID at the Bing Developer Center.

To add references to the Lync 2010 API

  1. In Microsoft Visual Studio development system, create a new C# Windows Presentation Foundation (WPF) application project.

  2. In Solution Explorer, right-click the application project and then click Add Reference.

  3. Go to the Browse tab and locate Microsoft.Lync.Model.dll. By default, this is installed in the %ProgramFiles%\Microsoft Lync\SDK\Assemblies\Desktop\Microsoft.Lync.Model.dll folder.

The Microsoft Lync 2010 SDK includes several components. One component lets you add WPF controls to your application which replicate some UI elements from the Microsoft Lync 2010 client. The component that you have previously added to your project is the automation component of the API, which lets you automate Lync client functions such as answering calls.

To create the screen pop window

  1. In Solution Explorer, open MainWindow.xaml. This is the window for your screen pop.

  2. In the Visual Studio Toolbox, drag two TextBlock objects onto the design surface. Name one of them phoneNumberTextBlock and the other callerInfoTextBlock. One object holds the caller’s phone number (or SIP URI) and the second object holds the details.

To demonstrate how a screen pop application might load account details from a web service, this sample performs a Bing search on the caller’s phone number, by using the Bing API. If you have not already created a Bing API AppID, you will have to do this at the Bing Developer Center before you continue. For more information, see Additional Resources.

To add a web service reference

  1. In Solution Explorer, right-click the project and then click Add Service Reference. The Add Service Reference dialog box appears.

  2. In the Add Service Reference dialog box, click Advanced, and then click Add Web Reference. The Add Web Reference dialog box appears.

  3. In the Add Web Reference dialog box, add a reference to http://api.bing.net/search.wsdl?AppID=[appid]&Version=2.2, where [appid] represents the AppID you received from the Bing Developer Center. Leave the web reference name as net.bing.api.

You are now ready to create the code for the screen pop.

In Visual Studio, open MainWindow.xaml.cs to edit the code-behind for the window.

In the Lync 2010 API, the LyncClient class is the starting point for all operations, and handles the communication with the Lync 2010 endpoint. The next example shows how to add an instance variable to the code file to hold the reference to the LyncClient object.

private LyncClient _lyncClient;

To retrieve a LyncClient object that represents the running instance of Lync, you can call the static method LyncClient.GetClient(). The next example shows how to use this method to retrieve an instance and assigns it to the _lyncClient variable.

public MainWindow()
{
    InitializeComponent();

    // Get the instance of LyncClient.
    _lyncClient = LyncClient.GetClient();
}

The screen pop has to load data when a call arrives. To be notified of all new conversations, the next example shows how the application subscribes to the ConversationAdded event on LyncClient.ConversationManager.

public MainWindow()
{
    InitializeComponent();
    _lyncClient = LyncClient.GetClient();
            
    _lyncClient.ConversationManager.ConversationAdded += 
        new EventHandler<Microsoft.Lync.Model.Conversation.ConversationManagerEventArgs>(
            ConversationManager_ConversationAdded);
}

NoteNote

This ConversationAdded event is invoked for outgoing conversations and with incoming conversations, and for all modalities. This means that, the way this screen pop is implemented, it will populate for outgoing PSTN calls also.

The code for the event handler appears in the next example. In the event handler, the application examines the SIP URI of the user who initiated the conversation. If this is an outgoing conversation, the initiator will be the same as the local user. In this case, the screen pop does not perform any action. This screen pop also ignores messages from non-PSTN contacts, although it is definitely possible to create a screen pop that responds to messages from users with a SIP URI.

void OnConversationAdded(object sender, Microsoft.Lync.Model.Conversation.ConversationManagerEventArgs e)
{
    // Get the properties for this conversation.
    IDictionary<ConversationProperty, object> properties = e.Conversation.Properties;

    // Get the Contact object for the person initiating the conversation.
    Contact inviterContact = e.Conversation.Properties[ConversationProperty.Inviter] as Contact;

    // Get the URI of the inviter.
    string inviterUri = inviterContact.Uri;

    // Try to match a phone number in the URI.
    Regex phoneRegex = new Regex(@"\+(\d+)");
    Match phoneMatch = phoneRegex.Match(inviterUri);

    string callerId = string.Empty;
    if (phoneMatch.Success)
    {
        // Load the data only if the caller is from a PSTN number.
        callerId = phoneMatch.ToString();
        LoadDataForCaller(callerId);
    }
}

If the application determines that the caller’s URI contains a phone number, it has to use the LoadDataForCaller method to load some data on the caller into the screen pop window. The next example shows how to add LoadDataForCaller.

private void LoadDataForCaller(string callerId)
{
    BingService service = new BingService();

    // Initiate a Bing search on the phone number.
    SearchRequest request = new SearchRequest();
    request.Query = callerId;
    request.AppId = ""; /* Fill in your Bing AppID here. */
    request.Sources = new SourceType[] { SourceType.Web };
    SearchResponse response = service.Search(request);

    // Turn the results into a simple list.
    StringBuilder webResultsBuilder = new StringBuilder();
    if (response.Web.Total > 0)
    {
        foreach (WebResult result in response.Web.Results)
        {
            webResultsBuilder.AppendLine(result.Title);
            webResultsBuilder.AppendLine(result.Description);
            webResultsBuilder.AppendLine(result.Url);
            webResultsBuilder.AppendLine();
        }
    }
    else
    {
        webResultsBuilder.Append("No search results.");
    }

    // Fill in the text blocks with the data.
    Dispatcher.Invoke(
        System.Windows.Threading.DispatcherPriority.Normal,
        new Action(delegate()
        {
            phoneNumberTextBlock.Text = callerId;
            callerInfoTextBlock.Text = webResultsBuilder.ToString();
        }
        ));
}

In this method, the application uses the Bing API web service to perform a Bing search on the phone number. It then builds the results into a string and fills the text blocks on the window with the caller’s phone number and the search results.

To test your screen pop application, run the WPF application while signed in to the Lync client, and place a PSTN call to your own phone number. After a second or two, the window should display your phone number and the results of a Bing search.

Many screen pop applications use the caller’s phone number as the key with which to look up information. Some, however, depend on information that is provided by the caller in an interactive voice response (IVR) menu or on other details that are not tied to the phone number. Traditional phone systems often use what is usually called computer telephony integration (CTI) to deliver information together with a call. Unfortunately, this information is lost when the call passes through the Mediation Server. Because the Mediation Server removes unrecognized SIP headers, even if CTI information is included in custom SIP headers on an incoming call, these will be removed by the Mediation Server before the call reaches the application.

However, a screen pop application can work together with server-side applications that are built by using the Microsoft Unified Communications Managed API (UCMA) to load information about a specific call. For an example of a contact center application that is built by using UCMA, see Contact Center sample. For more information, see Additional Resources.

Many server-side Lync applications handle customer calls as conferences in order to provide advanced functionality like call recording, reporting, or supervisor monitoring. A screen pop application can look at the conference URI on the incoming call when an agent is invited to the conference, and can use that URI as a unique ID to verify the call in a request to a web service. The next example shows how to retrieve the conference URI from the conversation properties.

string conferenceUri = 
    e.Conversation.Properties[ConversationProperty.ConferencingUri].ToString();
</code>

Server-side UCMA applications can perform various functions for customer calls, but as long as the application manages calls by using a conference, a screen pop can use this identifier to retrieve information that is associated with the specific call.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Lync.Model;
using Microsoft.Lync.Model.Conversation;
using System.Text.RegularExpressions;
using ScreenPop.net.bing.api;
using System.Configuration;

namespace ScreenPop
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private LyncClient _lyncClient;

        public MainWindow()
        {
            InitializeComponent();
            _lyncClient = LyncClient.GetClient();
            
            _lyncClient.ConversationManager.ConversationAdded += 
                new EventHandler<Microsoft.Lync.Model.Conversation.ConversationManagerEventArgs>(
                    OnConversationAdded);
        }

        void OnConversationAdded(object sender, Microsoft.Lync.Model.Conversation.ConversationManagerEventArgs e)
        {
            // Get the properties for this conversation.
            IDictionary<ConversationProperty, object> properties = e.Conversation.Properties;

            // Get the Contact object for the person initiating the conversation.
            Contact inviterContact = e.Conversation.Properties[ConversationProperty.Inviter] as Contact;

            // Get the URI of the inviter.
            string inviterUri = inviterContact.Uri;

            // Try to match a phone number in the URI.
            Regex phoneRegex = new Regex(@"\+(\d+)");
            Match phoneMatch = phoneRegex.Match(inviterUri);

            string callerId = string.Empty;
            if (phoneMatch.Success)
            {
                // Load the data only if the caller is from a PSTN number.
                callerId =  phoneMatch.ToString(); 
                LoadDataForCaller(callerId);
            }
        }

        private void LoadDataForCaller(string callerId)
        {
            BingService service = new BingService();

            // Initiate a Bing search on the phone number.
            SearchRequest request = new SearchRequest();
            request.Query = callerId;
            request.AppId = "9C741332068B0E7388E5D99F5AB6A8FB1D673872";
            request.Sources = new SourceType[] { SourceType.Web };
            SearchResponse response = service.Search(request);

            // Turn the results into a simple list.
            StringBuilder webResultsBuilder = new StringBuilder();
            if (response.Web.Total > 0)
            {
                foreach (WebResult result in response.Web.Results)
                {
                    webResultsBuilder.AppendLine(result.Title);
                    webResultsBuilder.AppendLine(result.Description);
                    webResultsBuilder.AppendLine(result.Url);
                    webResultsBuilder.AppendLine();
                }
            }
            else
            {
                webResultsBuilder.Append("No search results.");
            }

            // Fill in the text blocks with the data.
            Dispatcher.Invoke(
                System.Windows.Threading.DispatcherPriority.Normal,
                new Action(delegate()
                {
                    phoneNumberTextBlock.Text = callerId;
                    callerInfoTextBlock.Text = webResultsBuilder.ToString();
                }
                ));
        }
    }
}


Screen pop functionality is an important part of many contact centers, help desks, and other customer-facing business units. This article has shown how the Lync SDK is used to integrate a screen pop application into Lync with a minimal amount of code. By using the techniques appearing in this article, developers can create new screen pop applications for Lync or integrate their existing applications with the Lync client.

Michael Greenlee is currently a Senior Consultant at Avanade | LinkedIn.

Show:
© 2014 Microsoft