# Contact Data

SDK tracks two types of contacts: anonymous and identified. You start with an anonymous contact and identify them once you have their data - typically at login or registration.


# Create an anonymous contact

Call ping() to create an anonymous contact profile and start collecting data. A good place for this is right after SDK initialization.

UserSDK.default?.ping()

ping() sends device metadata (OS version, app version, device model, screen dimensions) to Positive User and creates a contact if one doesn't exist yet. Once the call completes, UserSDK.default?.userId is populated with the Positive User-generated identifier.


# Identify a contact

Once you have the contact's data - at login, registration, or profile update - call setUserData with any combination of standard attributes:

UserSDK.default?.setUserData([
    .firstName: "Jane",
    .lastName: "Doe",
    .email: "jane@example.com",
    .phone: "+1222333444",
    .userId: "your-internal-user-id"
])

setUserData calls ping() internally, so you don't need to call it separately. To remove a previously set value, pass nil:

UserSDK.default?.setUserData([.phone: nil])

# Add custom attributes

Send any additional attributes your product tracks:

UserSDK.default?.setCustomUserData([
    "plan": "pro",
    "signup_source": "organic",
    "trial_ends_at": "2024-12-31T00:00:00.000Z"
])

Custom attributes are merged with existing data on every call. To remove a value, pass nil for its key.


# Logout

When a contact logs out, call logout() to clear all stored data and create a fresh anonymous session:

UserSDK.default?.logout { success, error in
    // new anonymous contact session is ready
}

WARNING

logout() clears all local data immediately, even if the network request fails. Don't rely on the completion handler to indicate that server-side cleanup succeeded.