Nx10 Logo
Docs

3. SAAQ & Push Prompts

The Smart Delivery system for gathering emotional ground-truth from keyboards.

The Transient UI Problem

In a game, you can simply pause the action and display a UI popup. Keyboards are trickier: they are transient. A user might type a highly frustrated message, hit "Send", and instantly swipe the app away, dismissing the keyboard before we can ask them an SAAQ question.

To solve this, Nx10 uses a Smart Delivery System that dynamically chooses how to request a label depending on whether the user is still actively typing.

1. Keyboard SAAQ Overlay

If the user exhibits a kinematic deviation and is still actively using the keyboard, the Nx10 SDK will instantly replace the key-grid with a small, native-looking SAAQ module right inside the keyboard frame.

This requires zero code from you. It is handled entirely by the Nx10KeyboardViewController.

2. Actionable Push Notifications

If the user closes the app immediately after a kinematic deviation, the Nx10 backend detects that the keyboard session ended without a label. It will instantly trigger an APNs (Apple Push Notification) to the user's device.

Technical Constraint: Host App Routing

Can the Keyboard Extension receive Push Notifications directly? No.
Apple iOS strictly forbids App Extensions from registering for remote notifications. Push notifications must always be routed to the Host App. Therefore, your Host App acts as the delivery mechanism for these SAAQ prompts.

These are Interactive Push Notifications. The user doesn't even need to open the app; they can long-press the notification on their lock screen and directly tap "Frustrated" or "Calm" via iOS Notification Actions.

Enabling Smart Push in the Host App

  1. Request Push Notification permissions in your Host App.
  2. Pass the APNs Device Token to Nx10 using Nx10Core.shared.registerDeviceToken(token).
  3. Implement the UNNotificationResponse delegate in your Host App to forward the user's actionable button tap to the Nx10 SDK.
AppDelegate.swift
import UserNotifications
import Nx10Core

func userNotificationCenter(_ center: UNUserNotificationCenter, 
                            didReceive response: UNNotificationResponse, 
                            withCompletionHandler completionHandler: @escaping () -> Void) {
    
    // Check if this is an Nx10 Actionable SAAQ Push (e.g. they tapped "Frustrated")
    if Nx10Core.shared.isNx10Notification(response.notification) {
        
        // The SDK automatically parses the user's tapped action and sends the ground-truth
        // label to the Nx10 backend linked to their DeviceId.
        Nx10Core.shared.handleNotificationResponse(response)
    }
    
    completionHandler()
}