Data Component

By recording users’ keystrokes, developers can often obtain valuable data required for various purposes, from development to medical purposes. Fleksy Keyboard SDK supports capturing users’ input in detail. The developers can use the captured data in to ascertain information about users’ taps, words entered, time taken, type of layout, auto-corrected words, and much more.

When configured, the SDK starts capturing data every session and stores data after it. If the session includes multiple data points, the SDK starts storing data to reduce memory usage.

Data Object

The data captured by the Fleksy Keyboard SDK is in JSON format for easy parsing and readability and is either:

  • Sent as a callback event (Session on Android, DataCollection on iOS), or
  • Stored in a file with the .log extension at the given location during setup (filename: logger_typing_<timestamp>.log) as configured.

Example

The below example shows JSON data (object) in a file named logger_typing_b12b8c6a-256a-4fa0-8221-f086f80676b8.log captured after a session end.

Multiple tags have been collapsed for ease of readability. The captured file contains complete data.

{
    "sessionId": "b12b8c6a-256a-4fa0-8221-f086f80676b8",
    "startUnixTime": 1673809523412,
    "endUnixTime": 1673809546993,
    "timeZone": 5.5,
    "appContext": "co.thingthing.sample.sdksample",
    "textField": "Text",
    "language": "en-US",
    "languageVersion": "5100.0",
    "layout": "QWERTY",
    "screenSizePx": {
        "width": 1080.0,
        "height": 2400.0
    },
    "keyboardArea": {
        "x": 0.0,
        "y": 1739.0,
        "width": 1080.0,
        "height": 535.0
    },
    "screenSizeMm": {
        "width": 65.314285,
        "height": 145.14285
    },
    "performance": [],
    "keyTypes": [...
    ],
    "keyArea": [...
    ],
    "keyCode": [...
    ],
    "keyText": [...
    ],
    "pressTimes": [
        5434,
        6293,
        11365,
        12229,
        13122,
        13908,
        14523,
        15370,
        16348,
        19173,
        19847,
        20710,
        22223,
        23475
    ],
    "releaseTimes": [...
    ],
    "positionX": [...
    ],
    "positionY": [...
    ],
    "positionEndX": [...
    ],
    "positionEndY": [...
    ],
    "keyPress": [...
    ],
    "keyPressEnd": [...
    ],
    "keyCenter": [...
    ],
    "keyBounds": [...
    ],
    "emojis": [],
    "predictionTimes": [],
    "predictionLengths": [],
    "predictionWords": [],
    "autocorrectTimes": [],
    "autocorrectLengths": [],
    "autocorrectOriginalWords": [],
    "autocorrectWords": [],
    "wordsData": [
        {
            "originalWord": "",
            "word": "Trying",
            "autocorrection": false,
            "autocorrectionType": "",
            "autocorrectionValue": 0,
            "prediction": false,
            "swipe": false,
            "linkedKeyId": 0,
            "timestamp": 14608
        }
    ],
    "swipeData": [],
    "keyplaneData": {
        "switchplanes": [...
        ],
        "keyplanes": [...
        ]
    },
    "deleteData": [],
    "text": "Trying to type"
}

Initial Setup

Both Android and iOS variants of the Fleksy Keyboard SDK support capturing data which can be configured via the CaptureConfiguration block during the initial keyboard configuration. Furthermore, the data to be captured can also be configured using the FLDataConfiguration class that is taken as a parameter by the CaptureConfiguration class.

It is recommended to:

  • Get explicit consent from the user before capturing data to ensure compliance with required regulations as per regions,
  • Store the captured data within user-protected storage on supporting devices as they may contain sensitive information, and
  • Enable event logging only in debug or internal builds to avoid leaking the captured information to log files.

Examples

For Android:

To capture data on the Android platform, enable data capture by passing an instance of the CaptureConfiguration class. In addition, the data to be captured can be configured by using the FLDataConfiguration class as dataConfiguration parameter.

The below code sample showcases configuring data capture by storing the data in the application’s files directory.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import co.thingthing.fleksy.core.keyboard.KeyboardConfiguration
import co.thingthing.fleksy.core.keyboard.KeyboardConfiguration.CaptureConfiguration
import co.thingthing.fleksy.core.keyboard.KeyboardConfiguration.LicenseConfiguration
import co.thingthing.fleksy.core.keyboard.KeyboardService
import co.thingthing.fleksy.core.keyboard.models.FLDataConfiguration

class SampleKeyboardService : KeyboardService() {

    override fun createConfiguration(): KeyboardConfiguration {
        return KeyboardConfiguration(
            license = LicenseConfiguration(
                licenseKey = BuildConfig.FLEKSY_LICENSE_KEY,
                licenseSecret = BuildConfig.FLEKSY_SECRET_KEY
            ),
            capture = CaptureConfiguration(
                enabled = true,
                storeData = true,
                location = this.filesDir.absolutePath,
                dataConfiguration = FLDataConfiguration()
            )
        )
    }

}

For iOS:

Similar to Android, to capture data on the iOS platform, pass an instance of the CaptureConfiguration class. In addition, the captured data can be configured using the dataConfig parameter during instantiation that takes an instance of the FLDataConfiguration class.

The below code sample showcases configuring data capture by storing the data in the application’s files directory.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import UIKit
import FleksyKeyboardSDK

class KeyboardViewController: FleksyKeyboardSDK.FKKeyboardViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func createConfiguration() -> KeyboardConfiguration {

        // CAPTURE DATA
        // Capturing by default
        // if we want to disable it, pass false instead
        let dataConfig = FLDataConfiguration(
            configFormat: .dataConfigFormat_groupByTap,
            accelerometer: true
        )
        let capture = CaptureConfiguration(
            true,
            output: enumCaptureOutput.captureOutput_string,
            dataConfig: dataConfig
        )

        let style = StyleConfiguration()

        let appPopup = AppearancePopup()
        let appLongpress = AppearanceLongPress()
        let appearance = AppearanceConfiguration(
            objPopup: appPopup,
            objTouch: nil,
            objLongpress: appLongpress
        )

        let typing = TypingConfiguration()
        let panelConfig = PanelConfiguration()
        let debugConfig = DebugConfiguration(debug: ())

        let licenseConfig = LicenseConfiguration(
            licenseKey: "<your-license-key>",
            licenseSecret: "<your-license-secret>"
        )

        return KeyboardConfiguration(
            panel: panelConfig,
            capture: capture,
            style: style,
            appearance: appearance,
            typing: typing,
            specialKeys: nil,
            license: licenseConfig,
            debug: debugConfig
        )
    }
}

Properties

A data object has the following properties:

Property Name Unit Type Period Description Platform
accelerometerData object <Array> of <accelerometerObj> Event (x,y,z,timestamp) position of the accelerometer every x Hz Both
autocorrectTimes ms <Array> of <Numbers> as [Float] Event Time (relative to Start Time) corresponding to automatic spell correction events (milliseconds) Both
autocorrectLengths number <Array> of <Numbers> as [Integer] Event Length of the autocorrected word Both
autocorrectWords string <Array> of <String> as [UTF8] Event Autocorrected words Both
autocorrectOriginalWords string <Array> of <String> as [UTF8] Event Original autocorrected words Both
appContext name <String> as [UTF8] Session Current package name of the app where the keyboard is shown Both
deleteData object <Array> of <deleteObj> Event Record all delete events Both
distanceFromLastTouch number <Array> of <Numbers> as [Float] Event Euclidean distance from last touch (previous touch end to touch begin) Both
emojis string <Array> of <String> as [UTF32 as hex number] Event Transcription of the emojis typed Both
endUnixTime - - Session Timestamp for session end time Both
interKeyTimeHistogram number <Array> of 21 <Numbers> as [Integer] Event Interkey time histogram (previous touch begin to touch begin) Both
keyCode number <Array> of <Numbers> as [Integer] keystroke Keystroke character equivalent UTF8 Unicode in Decimal. First characters its equivalent to ASCII32. Both
keyTypes - <Array> of <String> as [UTF8] keystroke Key type indicating character family Both
keyArea number <Array> of <Numbers> as [Integer] keystroke Description of the area where the user has pressed. Values from 0 to 5 Both
keyPress pixels <Array> of <{x,y}> as [Float] keystroke Position of the keypress reference to the screen area in pixels Both
keyCenter pixels <Array> of <{x,y}> as [Float] keystroke Center of the key that we are pressing reference to the screen area in pixels Both
keyBounds pixels <Array> of <{x,y,width,height}> as [Float] keystroke Dimension of the key that we are pressing reference to the screen area in pixels Both
keyboardArea pixels {x: <Number>, y: <Number>, width: <Number> , height: <Number> } as [Integer] Session Keyboard area positioned inside the screen in pixels Both
keyplaneData object Object of two elements: switchplanes: <Array> of <switchplanesObj>, keyplanes: <Array> of <keyplanesObj> Event Record all key plane events change + the center and bounds of each key of the plane Both
language name <String> as [UTF8] Session Current language that the user is typing in. en-US Both
layout name <String> as [UTF8] Session Current layout used for the keyboard, which depend on the language and user preferences Both
performance number <Array> of <Numbers> as [Float] Event Current CPU usage to understand the progression of the device iOS
positionX pixels <Array> of <Numbers> as [Integer] keystroke Position from the center of the key dimension X, in pixels Both
positionY pixels <Array> of <Numbers> as [Integer] keystroke Position from the center of the key dimension Y, in pixels Both
pressTimes - - keystroke Time (relative to Start Time) corresponding to key press event (milliseconds) Both
predictionTimes ms <Array> of <Numbers> as [Float] Event Time (relative to Start Time) corresponding to press events on word pressed on the suggestion bar (milliseconds) Both
predictionLengths number <Array> of <Numbers> as [Integer] Event Length of the pressed predicted word Both
predictionWords string <Array> of <String> as [UTF8] Event Words pressed for inserting them as predicted Both
releaseTimes - - keystroke Time (relative to Start Time) corresponding to key release event (milliseconds) Both
screenSizeMm mm {width: <Number> , height: <Number> } as [Floats] Session Screen size of the phone/tablet in mm Both
screenSizePx pixels {width: <Number> , height: <Number> } as [Integer] Session Screen size of the phone/table in pixels, total number of pixels Both
startUnixTime ms <Number> as [Integer] Session Timestamp for session start time Both
swipeData object string and numbers <Array> of <swipeObj> Word Collection of all data related to a trace on top of the keyboard to detect a word Both
tapEvent - - - - -
text - <String> as [UTF8] Session Transcription of final text input content by end of session Both
textField name <String> as [UTF8] Session Current Textfield where the user wrote. Both
timeZone hours <Number> as [Float] Session Current Timezone referenced to GMT Both
wordsData object string and numbers <Array> of <wordsObj> Word Information related to each of the words Both

accelerometerData

Position (x,y,z,timestamp) of the accelerometer every x Hz. It contains an <Array> of <accelerometerObj>.

An instance of accelerometerObj contains the following values:

Property Name Type Description
x <number> as [Float] x position
y <number> as [Float] y position
z <number> as [Float] z position
timestamp number Time from the start of the session

deleteData

Record all delete events. It contains an <Array> of <deleteObj>.

An instance of deleteObj contains the following values:

Property Name Type Description
word string Word being delete before applying the delete action
delete string Character to delete
type number Type of delete

0 – Delete a Character
1 – Delete a Space
2 – Delete action that undo previous AC
timestamp number Time from the start of the session

interKeyTimeHistogram

This histogram will be stored as <Array> of 21 <Numbers> as [Integer]. It indicates the count of interkey times in a typing session that are in each of the bins as specified below:

  • The first bin 0-0.05 sec,
  • The second 0.05 to 0.10 sec,
  • The third 0.10-0.15 sec,
  • …,
  • The 20th bin 0.95-1.0 sec.

keyArea

Description of the area where the user has pressed. Values from 0 to 5.

This object contains the following values:

  • “1” for letters QWASZ
  • “2” for letters ERDFXC
  • “3” for letters TYGV
  • “4” for letters UIHJBN
  • “5” for letters OPKLM

keyCode

Keystroke character equivalent UTF8 Unicode in Decimal. First characters its equivalent to ASCII32.

Note: Number 900 makes reference to emoji. The transcription of this emoji it is in the array of emojis, by order.

Note: Number 901 makes reference to a prediction.

keyTypes

Key type indicating character family.

This object contains the following values:

  • “an”: Alphanumeric
  • “pt”: Symbols and punctuation
  • “sp”: Space bar
  • “bk”: Backspace
  • “en”: Enter
  • “md”: Modifier key
  • “shf”: Shift
  • “atcshf”: Automatic shift
  • “atcmd”: Automatic numbers
  • “eksw”: Emoji button / keyboard from emoji
  • “pred”: Prediction from the topbar
  • “sugg”: Suggestion from the topbar
  • “ukn”: Others

keyplaneData

Record all key plane events change + the center and bounds of each key of the plane. It contains an <Array> of <switchplanesObj> and <Array> of <keyplanesObj>.

For example:

{
    "keyplaneData": {
        "switchplanes": [
            {
                "keyplane": 0,
                "label": "",
                "keytype": "atcshf",
                "timestamp": 5554
            }
        ],
        "keyplanes": [
            {
                "keyplane": 0,
                "keys": [
                    {
                        "center": {
                            "x": 54.0,
                            "y": 1805.8749980926514
                        },
                        "bounds": {
                            "x": 0.0,
                            "y": 1739.0,
                            "width": 108.0,
                            "height": 133.74999618530273
                        },
                        "label": "q"
                    },
                    {
                        "center": {
                            "x": 162.0,
                            "y": 1805.8749980926514
                        },
                        "bounds": {
                            "x": 108.0,
                            "y": 1739.0,
                            "width": 108.0,
                            "height": 133.74999618530273
                        },
                        "label": "w"
                    }
                ]
            }
        ]
    },
    ...
  },
}

An instance of switchplanesObj contains the following values:

Property Name Type Description
keyplane number Type of keyplane – these values are present in the FLEnums.h if you are interested
label <string> as [UTF8] Label associated with key if any
keytype <string> as [UTF8] Keytype of the key pressed from the list of keytypes.
timestamp number Time from the start of the session

An instance of keyplanesObj contains the following values:

Property Name Type Description
keyplane string Type of keyplane
keys <Array> of <KeysObj> -

An instance of KeysObj contains the following values:

Property Name Type Description
center - “x”: <number> as [Float]
“y”: <number> as [Float]
bounds - “x”: <number> as [Float]
“y”: <number> as [Float]
“width”: <number> as [Float]
“height”: <number> as [Float]
label <string> as [UTF8] Letter detected

swipeData

Collection of all data related to a trace on top of the keyboard to detect a word. It contains an <Array> of <swipeObj>.

An instance of swipeObj contains the following values:

Property Name Type Description
layout string Word being delete before applying the delete action
context string Previous word of the swipe
candidate string Word that we’re guessing
word string Word final written
selectedSuggestion string This is empty unless the user presses one of the suggestions of the topbar.
points <Array> of <Points> -
timestamp number Time from the start of the session
candidates <Array> of <Candidates> -

An instance of Points contains the following values:

Property Name Type Description
x <number> as [Float] x position
y <number> as [Float] y position
l <string> as [UTF8] Letter detected
t <number> Path point timestamp from start of the session

An instance of Candidates contains the following values:

Property Name Type Description
w <string> as [UTF8] Word
s <number> Shape log probability
f <number> Final log probability

tapEvent

The tapEvent object gets generated in case of selecting the option of “Format group by tap”, which groups all keyStroks in one object per key stroke.

Property Name Unit Type Period Description Platform
keyArea number <Array> of <Numbers> as [Integer] keystroke Description of the area where the user has pressed. Values from 0 to 5 Both
keyBounds pixels <Array> of <{x,y,width,height}> as [Float] keystroke Dimension of the key that we are pressing reference to the screen area in pixels Both
keyCenter pixels <Array> of <{x,y}> as [Float] keystroke Center of the key that we are pressing reference to the screen area in pixels Both
keyCode number <Array> of <Numbers> as [Integer] keystroke Keystroke character equivalent UTF8 Unicode in Decimal. First characters its equivalent to ASCII32. Both
keyIdentifier - - - Different <number> for each tapEvent during a session. It restarts every session. Both
keyText - - - Current text pressed, which could be a character, an emoji, prediction word Both
keyTypes - <Array> of <String> as [UTF8] keystroke Key type indicating character family Both
touchBegin - - - - -
touchEnd - - - - -

The properties touchBegin and touchEnd contains the following values:

  • “press”: <obj> | position of the press
    • “x”: <number> | x position
    • “y”: <number> | y position
  • “distance”: <obj> | distance from between the center of the key and the press position
    • “x”: <number> | x position
    • “y”: <number> | y position
  • “timestamp”: <number> | time from the start of the session

textField

Current Textfield where the user wrote.

This object contains the following values:

  • “Text”: Regular Text field
  • “Pwd”: Password text field
  • “Url”: URL text field
  • “Email”: Email text field
  • “Numbers”: Numbers text field
  • “Twitter”: Twitter text field, used in Twitter/Slack / …
  • “Websearch”: Websearch textfield
  • “Text_ACOFF”: Regular text field without Autocorrection
  • “Twitter_ACOFF”: Twitter text field without AC

wordsData

Information related to each of the words. It contains an <Array> of <wordsObj>.

For example:

{
    "wordsData": [
        {
            "originalWord": "",
            "word": "Trying",
            "autocorrection": false,
            "autocorrectionType": "",
            "autocorrectionValue": 0,
            "prediction": false,
            "swipe": false,
            "linkedKeyId": 0,
            "timestamp": 14608
        }
    ],
    ...
  },
}

An instance of wordsObj contains the following values:

Property Name Type Description
originalWord string Original word written (in case of AC, Prediction or swipe)
word string Word recorded
autocorrection bool It comes from an autocorrection
prediction bool It comes from a prediction
swipe bool It comes from a swipe typing
autocorrectionType string Type of autocorrection in case of autocorrection true.

Values:
“missedSpace” – in this case value is number of words splitted into
“missTypedSpace” – Miss an space
“eliminated” – Characters deleted
“transposition” – Value of characters changed
“missingTap” – Value of missed taps in the word
”" – empty in case of no type
autocorrectionValue number Value related to autocorrectionType
timestamp number Time from the start of the session
linkedKeyId number Linked id with the tapEvent that caused this word. When the word is autocorrected, it would be associated with the corresponding Id in the tapEvent array. “0” means no id linked from tapEvent.
unip number Unigram log probability of this word

Additional Resources

For more information, consider checking out the API reference documentation for the respective platform, which documents all the available methods to customize the keyboard built with Fleksy Keyboard SDK.


Something needs to be added, or found an error in our documentation? Please let us know by either on our GitHub or Discord.

Last updated on January 31, 2023