Screen Pop: Architecture & Implementation Overview Screen pop is the automatic display of a customer record when they call. Agent's desktop automatically looks up the caller by phone number and displays their Salesforce record. Benefits: No manual lookup needed (saves 30+ seconds per call) Agent sees customer context immediately Fewer wrong accounts selected Better first-call resolution How It Works (The Flow) Customer calls (ANI: +15551234567) ↓ Architect Flow receives call ↓ Data Action: Look up contact by phone in Salesforce API ↓ Salesforce returns: Contact ID + Account info ↓ Flow sets Interaction Attributes: - contact_id = "003xx000003SG" - account_id = "001xx000002Edc" ↓ Flow transfers to Support Queue ↓ Agent receives call ↓ Agent's desktop extension reads Interaction Attributes ↓ Desktop makes API call to Salesforce: GET /sobjects/Contact/003xx000003SG ↓ Browser pops Salesforce record in new window ↓ Agent sees: Name, account, cases, history ↓ Agent handles call with context Architecture Components 1. Call Entry Point (Architect Flow) The flow that receives inbound calls: START ↓ Play: "Thank you for calling..." ↓ Data Action: lookup-contact-by-phone Input: ${interaction.caller.phoneNumber} Output: ${contact.id}, ${account.id} ↓ Decision: Contact found? YES → Set attributes → Transfer NO → Collect account number → Transfer ↓ Transfer to Queue (attributes go with call) ↓ END 2. Data Action (API Call) { "name": "lookup-contact-by-phone", "method": "POST", "url": "https://your-instance.salesforce.com/services/apexrest/contact-lookup", "inputContract": { "phoneNumber": { "type": "string", "required": true } }, "outputContract": { "success": { "type": "boolean" }, "contactId": { "type": "string" }, "firstName": { "type": "string" }, "lastName": { "type": "string" }, "accountId": { "type": "string" }, "accountName": { "type": "string" }, "tier": { "type": "string" } } } 3. Interaction Attributes Data attached to the call that agent's desktop can access: { "contact_id": "003xx000003SG", "contact_name": "John Doe", "account_id": "001xx000002Edc", "account_name": "Acme Corp", "customer_tier": "Premium", "last_contact": "2026-03-10T14:30:00Z" } 4. Agent Desktop Extension JavaScript in the Genesys Workspace (desktop app or web): // Listen for incoming interaction genesysClient.on('interaction.incoming', async (interaction) => { // Get attributes set by flow const contactId = interaction.attributes?.contact_id; if (contactId) { // Pop Salesforce record const recordUrl = `https://your-instance.salesforce.com/${contactId}`; window.open(recordUrl, 'salesforce'); } }); Step-by-Step Implementation Step 1: Create Salesforce Apex Endpoint // ContactLookupController.cls @RestResource(urlMapping='/contact-lookup') global class ContactLookupController { @HttpPost global static LookupResponse lookup(String phoneNumber) { LookupResponse response = new LookupResponse(); try { // Search for contact by phone List contacts = [ SELECT Id, FirstName, LastName, Email, AccountId, Account.Name, Custom_Tier__c FROM Contact WHERE Phone = :phoneNumber OR MobilePhone = :phoneNumber LIMIT 1 ]; if (contacts.isEmpty()) { response.success = false; return response; } Contact contact = contacts[0]; response.success = true; response.contactId = contact.Id; response.firstName = contact.FirstName; response.lastName = contact.LastName; response.accountId = contact.AccountId; response.accountName = contact.Account?.Name; response.tier = contact.Custom_Tier__c; } catch (Exception e) { response.success = false; response.error = e.getMessage(); } return response; } global class LookupResponse { public Boolean success; public String contactId; public String firstName; public String lastName; public String accountId; public String accountName; public String tier; public String error; } } Step 2: Create Architect Flow In Genesys Architect → Create Inbound Call Flow : Flow Steps: 1. START ↓ 2. Play Audio: "Thank you for calling..." ↓ 3. Data Action: lookup-contact-by-phone Input: ${interaction.caller.phoneNumber} ↓ 4. Decision: ${dataAction.result.success}? IF YES: └─ Set Agent Variables: - contact_id = ${dataAction.result.contactId} - contact_name = ${dataAction.result.firstName} ${dataAction.result.lastName} - account_id = ${dataAction.result.accountId} - account_name = ${dataAction.result.accountName} - customer_tier = ${dataAction.result.tier} IF NO: └─ Play Audio: "Please hold while we locate your account..." ↓ 5. Transfer to Queue: Support Queue ↓ 6. DISCONNECT Step 3: Create Desktop Extension In Genesys Cloud → Integrations → Custom Apps → Desktop App Extensions : // manifest.json { "version": "1.0", "name": "Salesforce Screen Pop", "description": "Pops Salesforce contact on inbound call" } // index.html Handling Edge Cases Multiple Matches Problem: Phone number found 3 contacts (different names, same company) Solution: Let agent pick Flow: Decision - ${dataAction.result.matches.length} > 1? IF YES: └─ Play: "Multiple accounts found. Press..." └─ Collect Input: "Press 1 for John Doe" "Press 2 for Jane Doe" "Press 3 for John Smith" └─ Set contact_id = ${dataAction.result.matches[input]}.id IF NO: └─ Continue normally Contact Not Found Problem: Phone number not in Salesforce Solution: Offer fallback Flow: Decision - ${dataAction.result.success}? IF NO: └─ Play: "Account not found. Please enter your account number..." └─ Collect Input: Account Number └─ Data Action: lookup-by-account-number └─ Set attributes if found └─ Transfer without pop if not found Slow Lookup (Timeout) Problem: Salesforce API slow, lookup takes 5+ seconds Solution: Don't block the call Flow: Data Action: lookup-contact-by-phone Timeout: 3 seconds Decision: Action succeeded? IF YES (within 3 sec): └─ Set attributes → Transfer IF NO (timed out): └─ Play: "Connecting you now..." └─ Transfer WITHOUT attributes └─ (Agent can manual search) Salesforce Field Mapping What agent sees after screen pop: Data Point Source Salesforce Record Contact Name Flow attribute Contact.Name Email API response Contact.Email Phone API response Contact.Phone Account Flow attribute Account.Name Tier/Priority Flow attribute Contact.Custom_Tier__c Recent Cases (automatic in SF) Related Cases Contact History (automatic in SF) Activity Timeline Performance Optimization Problem: Lookup taking 2+ seconds Causes: Salesforce API slow Network latency SOQL query inefficient Solutions: Add Index in Salesforce -- Make phone lookups fast CREATE INDEX idx_contact_phone ON Contact(Phone, MobilePhone); Cache recent lookups class ScreenPopCache { constructor(ttlSeconds = 3600) { this.cache = new Map(); this.ttl = ttlSeconds; } async lookup(phone) { const cached = this.cache.get(phone); if (cached && Date.now() - cached.timestamp < this.ttl * 1000) { return cached.data; } const result = await callSalesforceAPI(phone); this.cache.set(phone, { data: result, timestamp: Date.now() }); return result; } } Use webhook instead of polling Salesforce creates contact → webhook updates Genesys (More advanced, requires webhook setup) Testing Screen Pop Manual Test Configure test flow in Architect Set up desktop extension locally Make test call to your Genesys DID Verify: ✓ Architect flow receives call ✓ Data Action executes (check execution history) ✓ Salesforce API returns contact ✓ Flow sets interaction attributes ✓ Desktop receives attributes ✓ Window pops Salesforce record Automated Test // test-screen-pop.js async function testScreenPop() { // 1. Test Salesforce lookup const contact = await lookupContactByPhone('+15551234567'); console.assert(contact.id, 'Contact not found'); // 2. Test Genesys Data Action const result = await callDataAction('lookup-contact-by-phone', { phoneNumber: '+15551234567' }); console.assert(result.success, 'Data Action failed'); // 3. Test flow const call = await makeTestCall('+15551234567'); const attributes = call.attributes; console.assert(attributes.contact_id, 'No contact_id in attributes'); console.log('✓ Screen pop test passed'); } Troubleshooting Problem: Desktop doesn't pop window Check: Extension enabled in Genesys Workspace? Flow sets interaction attributes? Desktop JavaScript can access attributes? Browser allows popups? Salesforce URL correct? Debug: // Add logging to desktop extension genesysClient.on('interaction.incoming', (interaction) => { console.log('Attributes:', interaction.attributes); console.log('Contact ID:', interaction.attributes?.contact_id); }); Problem: Lookup returns "Contact not found" for valid phone Check: Phone in Salesforce exactly matches flow phone? Phone format consistent (E.164, local, international)? Apex query correct? Debug: // Test in Salesforce Developer Console List contacts = [ SELECT Id FROM Contact WHERE Phone = '+15551234567' ]; System.debug(contacts.size() + ' contacts found'); Problem: Performance is slow Check: Data Action timeout too long? Salesforce API slow? Network latency high? Optimize: Set timeout to 3 seconds (not 10) Add Salesforce index on Phone field Implement caching Use webhook instead of API call Production Deployment Checklist Salesforce Apex endpoint created & tested Data Action configured in Genesys Architect flow configured & tested Desktop extension installed & enabled Error handling for timeouts Fallback for not-found contacts Field mapping verified Performance acceptable (<3 sec) Monitoring & alerting set up Staff trained on screen pop behavior Related Topics Chapter 11: API Endpoints Reference (Salesforce API) Chapter 11: Error Handling & Retry Strategy Chapter 5: Data Actions (in Architect flows) Chapter 12: Contact Sync from Salesforce