Every public class of the Personyze Android SDK 2.1, in the package com.personyze.android (the composable is in com.personyze.android.compose). How to put them together is in the Android SDK guide.
None of these throw for a network or server problem. A failed call answers an empty result with its error set, and every failure reaches the error listener. Only programming errors throw, such as an empty API key or a baseUrl that is not https://.
Personyze
The entry point: an object that forwards every call to the client created by initialize.
| Member | |
|---|---|
initialize(context: Context, config: PersonyzeConfig): PersonyzeClient |
Creates the client. Call it once, in Application.onCreate. Called again with the same settings it changes nothing; with others (another key) it replaces the client. |
isInitialized: Boolean |
Whether initialize has been called. |
client: PersonyzeClient |
The client itself, with the same members as Personyze, and diagnostics(): String: the stored state with the key and the push token left out or cut short, for a support case. Throws IllegalStateException before initialize. |
result: StateFlow<PersonyzeResult> |
The current decision. Every response updates it, and it is restored when the app starts. |
visitor: StateFlow<PersonyzeVisitor> |
The current visitor and session. |
pushStatus: StateFlow<PersonyzePushStatus> |
Where push stands on this install: see PersonyzePushStatus. |
suspend navigate(document: String, events: (PersonyzeEvents.() -> Unit)? = null): PersonyzeResult |
The visitor opened a screen: logs a page view and answers what to present there, in one request. The events in the block run first and go in the same request. Call it once per screen entry. |
suspend refresh(): PersonyzeResult |
Sends what is queued and answers the current decision with the response's changes. With nothing queued, it answers the current decision without a request. |
suspend flush() |
Sends what is queued now, instead of waiting for the automatic send. |
setUserId(userId: String?), setUserId(userId: Long) |
Identifies the visitor with your own user id, after login. null logs out, back to the installation's anonymous visitor. |
startNewSession() |
Starts a new session with the next request. A session otherwise lasts 90 minutes from its start. |
suspend reset() |
A new anonymous visitor; everything stored for the old one is deleted (session, queued events, decision, history). |
suspend clearCache() |
Forgets the cached action and campaign templates and loads them again. Normally never needed. |
reportExecuted(actionId: Int) |
The action was shown. |
reportEngaged(actionId: Int) |
The visitor tapped the action's call to action: the Clicks criterion of an A/B test, and only that. |
reportClosed(actionId: Int, dontShowForSessions: Int = 0) |
The visitor closed the action; with a number above 0 it is not presented again for that many sessions. |
reportProductClicked(actionId: Int, productId: String), reportArticleClicked(actionId: Int, articleId: String) |
The visitor tapped a product or an article the action recommended. |
reportError(actionId: Int, message: String) |
The action could not be presented. |
report(click: PersonyzeClick) |
Reports a tap, as the renderers do. |
suspend checkNotifications(): PersonyzeNotification? |
Checks for a notification now, outside the schedule, and shows it. Answers what was shown, or null. |
setNotificationsEnabled(enabled: Boolean) |
Turns the notifications on or off: the periodic check, and the device's push registration. Turned off, Personyze stops pushing to the device. |
setPushToken(token: String) |
The token Firebase Cloud Messaging gave the app. Pass it from your FirebaseMessagingService.onNewToken, and each time the app comes to the front (FirebaseMessaging.getInstance().token). Personyze then pushes this visitor's notifications to the device at once, when the account has uploaded its Firebase service account. |
handlePushMessage(data: Map<String, String>): Boolean |
A push message, as your FirebaseMessagingService.onMessageReceived gets it (message.data). If it is Personyze's, the SDK shows it, reports it shown and answers true. It waits for the pictures, 15 seconds at most. Anything else answers false and is yours to handle. |
suspend verdict(conditionId: Int): Result<PersonyzeVerdict> |
Who is winning the A/B test of a campaign. |
Called before initialize, the events and reports are ignored (and logged), and the suspend calls answer an empty result.
Events
Each call queues one event and returns at once; all are safe to call from any thread. The queue goes out with the next navigate, or by itself 3 seconds after the last event, or when the app goes to the background. Product and article ids are the Internal ID in your catalog. actionId attributes the event to the action that showed the item: with it, a purchase counts for the Products purchased criterion of that action's A/B test.
| Event | |
|---|---|
setProfile(field: String, value: String?) |
A profile field: email, first_name, or any field of your own. |
setProfile(fields: Map<String, String?>) |
Several profile fields at once. |
productViewed(productId: String, actionId: Int? = null) |
|
productAddedToCart(productId: String, actionId: Int? = null, quantity: Int? = null) |
|
productRemovedFromCart(productId: String, actionId: Int? = null, quantity: Int? = null) |
|
productLiked(productId: String, actionId: Int? = null) |
Added to a wishlist or favorites. |
productUnliked(productId: String, actionId: Int? = null) |
Removed from the wishlist. |
productPurchased(productId: String, actionId: Int? = null, quantity: Int? = null) |
|
productsPurchased() |
Everything reported added to cart was purchased. |
productsRemovedFromCart() |
The cart was emptied. |
productsUnliked() |
The wishlist was emptied. |
articleViewed(articleId: String, actionId: Int? = null) |
|
articleLiked, articleCommented, articleUnliked |
The same parameters. |
articleGoal(articleId: String, actionId: Int? = null) |
The visitor reached the article's goal. |
articlesUnliked() |
|
promotionViewed(promotionId: String, actionId: Int) |
A card of a promotions action came into view. promotionId is the card's data-personyze-click-target="promotions <id>". |
promotionClicked(promotionId: String, actionId: Int) |
|
codeRevealed(promotionId: String, actionId: Int) |
The visitor revealed the promotion's coupon code. |
couponUsed(code: String) |
A coupon code was redeemed. |
track(command: List<String>) |
Any tracker command, sent as given, in a request of its own. |
A blank id, or a promotion without its action id, is not sent: the call is ignored and the error listener gets a PersonyzeException.Invalid.
PersonyzeConfig
The settings, built with a block:
PersonyzeConfig("YOUR_API_KEY") {
notifications = true
timeout = 3.seconds
}
| Setting | Default | |
|---|---|---|
baseUrl |
https://app.personyze.com |
Where the API is. https:// only. |
assetsUrl |
https://counter.personyze.com/ |
Where Personyze's WebView library is served from. |
timeout |
5 seconds | The time a decision may take, every attempt included. A slower one fails, and the app shows its default. |
backgroundTimeout |
10 seconds | The same for what no screen waits for: queued events, templates, notifications. |
retries |
1 | 0 or 1. A retry happens only after a connection failure, a timeout or a server error, and only within the time limit. |
notifications |
false | Show notifications from "Web Push Send" actions. The app must declare POST_NOTIFICATIONS. |
notificationChannelName |
Recommendations |
The notification channel's name in the system settings. |
notificationSmallIcon |
the SDK's bell | A drawable resource for the status bar, used when the message has no badge of its own. |
autoFlushDelay |
3 seconds | How long queued events wait for more before going out by themselves. null: only with the next navigate, a flush(), or the app going to the background. |
storageName |
default |
Keeps a separate visitor and state under this name: for a second account. Letters, digits, - and _. |
okHttpClient |
none | An OkHttpClient of your own, for a proxy or certificate pinning. An interceptor of yours that logs headers would log the API key. |
onError |
none | A PersonyzeErrorListener. |
PersonyzeResult
What Personyze decided for the visitor: the campaigns they match and the actions to present. navigate replaces it; events and reports sent without a navigation add to it, and remove what Personyze withdrew.
| Member | |
|---|---|
actions: List<PersonyzeAction> |
The actions to present, in the order Personyze sent them. |
conditions: List<PersonyzeCondition> |
The campaigns the visitor matches, for logic of your own. |
has(actionId: Int): Boolean |
Whether this action was decided. What an A/B test in your own code branches on. |
action(actionId: Int): PersonyzeAction? |
The action, if it was decided. |
firstOf(vararg actionIds: Int): Int? |
The first of these actions that was decided. |
actionsIn(placeholder: String): List<PersonyzeAction> |
The actions targeted to a placeholder, by its name or HTML id in the panel: in placeholder order, and no more than the placeholder holds. Also takes the placeholder's numeric id. |
dataFor(actionId: Int): Map<String, String>? |
An action's per-visitor values. |
dismissedActions: List<Int>, dismissedConditions: List<Int> |
What Personyze withdrew in the last response that was not a navigation. |
isEmpty: Boolean |
No actions and no campaigns. |
failed: Boolean, error: PersonyzeException? |
Whether it is empty because the request failed, and why. |
sessionId: String?, cacheVersion: Int |
The session and the account version it was decided in. |
rawJson: String? |
The response as it came, for anything this class does not model. |
PersonyzeAction
An action Personyze decided to present: usually HTML (a banner, a recommendation widget), sometimes JSON or text that you render yourself. The decision and the action's per-visitor data arrive first; the template arrives a moment later and is cached.
| Member | |
|---|---|
id: Int |
The action's id. |
name: String? |
Its name in the panel. |
contentType: String? |
text/html for banners and recommendation widgets, application/json for a JSON feed. |
isHtml: Boolean, isJson: Boolean |
The same, as flags. |
isLoaded: Boolean |
Whether the template has arrived. Until then content is null, and the result updates again when it comes. |
content: String? |
The content, ready to use. |
data: Map<String, String> |
The values Personyze computed for this visitor: product lists, texts. |
placeholders: List<PersonyzePlaceholder> |
The placeholders it is targeted to. |
placeholderOrder: Int? |
Its order among the actions in a placeholder; null means last. |
libs: List<String> |
The helper scripts its HTML needs. |
contentJsonArray(): List<Map<String, String>>? |
For a JSON feed: its rows, every value as text. |
contentHtmlDocument(): String? |
For an HTML action: a complete page that runs it in a WebView of your own, with Personyze's library and click handling. |
reportExecuted(), reportEngaged(), reportClosed(dontShowForSessions: Int = 0), reportProductClicked(productId: String), reportArticleClicked(articleId: String), reportError(message: String) |
The reports of this action. |
PersonyzeCondition
A campaign the visitor matches: id: Int, and name: String?, its name in the panel.
PersonyzePlaceholder
A placeholder an action is targeted to. In an app, a named slot of your own.
| Member | |
|---|---|
id: Int |
|
name: String |
Its name in the panel. |
htmlId: String |
The HTML id or selector set in the panel. |
unitsCountMax: Int |
How many actions it holds; 0 means no limit. |
PersonyzeActionView
A View (a FrameLayout) that renders an HTML action in a WebView and reports what happens in it. It can be created in code or in a layout.
| Member | |
|---|---|
render(action: PersonyzeAction) |
Shows the action. The same action with the same content again does nothing, so it is safe to call on every update. |
clear() |
Shows nothing. |
destroy() |
Releases the WebView. Call it when the screen is gone; the view can render again afterwards. |
action: PersonyzeAction? |
The action shown. |
onClick: PersonyzeClickListener? |
Called for each tap, after it is reported. |
reportExecuted: Boolean |
Report the action shown once its page has loaded. Default true. |
reportClicks: Boolean |
Report the taps. Default true. |
autoHeight: Boolean |
Take the content's height when the view's height is not fixed. Default true. |
A tap that the click listener does not handle does the default: a link opens in the browser, and a close hides the view.
PersonyzeActionContent
The Compose version of PersonyzeActionView, in personyze-android-compose:
@Composable
fun PersonyzeActionContent(
action: PersonyzeAction,
modifier: Modifier = Modifier,
reportExecuted: Boolean = true,
reportClicks: Boolean = true,
onClick: ((PersonyzeClick) -> Boolean)? = null
)
It takes the content's height unless modifier sets one, and releases its WebView when it leaves the composition. onClick returns true when the app handled the tap.
PersonyzeClick
A tap inside a rendered action.
| Member | |
|---|---|
actionId: Int |
|
kind: PersonyzeClick.Kind |
TARGET (the call to action), CLOSE (a close or "don't show again" button), PRODUCT or ARTICLE (a recommended item). |
href: String |
The link's address when a link was tapped, else empty. |
productId: String?, articleId: String? |
The item's Internal ID, for PRODUCT and ARTICLE. |
dontShowForSessions: Int |
For CLOSE: how many sessions not to show the action again; 0 just closes it. |
PersonyzeClickListener is the handler: fun onClick(click: PersonyzeClick): Boolean, returning true when the app handled the tap.
PersonyzeVisitor
Who Personyze is talking about right now, from Personyze.visitor.
| Member | |
|---|---|
userId: String? |
The id set with setUserId, or null for the installation's anonymous visitor. |
visitorId: Int? |
The id Personyze files the visitor under: your numeric user id, a number made from a text one, or the installation's own. |
sessionId: String? |
The current session, or null before the first request. |
PersonyzeNotification
A notification the SDK showed, as checkNotifications() answers it: messageId, title, body, url (where a tap goes), imageUrl, iconUrl, badgeUrl, buttons (each with title, iconUrl and url), silent, renotify, and vibrate (a pattern in milliseconds).
PersonyzePushStatus
Where push stands on this install, from Personyze.pushStatus: what a screen of your app, or a support case, can show when notifications do not arrive at once. Its toString() cuts the token short.
| Member | |
|---|---|
token: String? |
The token the app passed on with setPushToken, or null. |
registeredVisitorId: Int? |
The visitor Personyze has this device registered for, or null. |
registeredAtMs: Long |
When it was last registered, in milliseconds since the epoch; 0 for never. |
pushed: Boolean |
Whether Personyze pushes to this device: the account has uploaded its Firebase service account. |
| State | What it means |
|---|---|
No token |
The app has not passed one on. Notifications appear when the app checks. |
A token, no registeredVisitorId |
Not registered yet. That happens after the app's first request (a navigate, events or a refresh), and again after a login or logout. Or notifications are turned off. |
Registered, pushed false |
The account has no Firebase service account in the panel (Settings › Integrations › App push). The device is registered all the same, so a key added later reaches it. |
pushed true |
A campaign's notification reaches this device at once. |
PersonyzeVerdict
Who is winning an A/B test, as verdict(conditionId) answers it. The same comparison the panel shows; see ab_test for what each value means.
| Member | |
|---|---|
conditionId: Int, conditionName: String |
The campaign. |
hasWinner: Boolean |
True only when every goal passed its thresholds and they all name the same arm. |
winnerActiongroupId: Int? |
The winning arm. |
message: String |
Why there is no winner yet, in words; empty once there is one. |
controlGroupRotation: Double, maxDurationReached: Boolean |
|
goals: List<PersonyzeVerdict.Goal> |
Per goal: title, best and comparedTo (arms), significancePrc, improvementPrc (in percentage points), the thresholds, reached, summary, and every arm's numbers in groups. |
rawJson: String |
The response as it came. |
PersonyzeException
What the error listener receives, and what PersonyzeResult.error holds. The SDK never throws these at your code. No message ever contains the API key.
| Type | |
|---|---|
PersonyzeException.Auth |
Personyze rejected the API key (HTTP 401). Check it in Settings › Integrations. |
PersonyzeException.BadRequest |
Personyze refused the request. status is the HTTP status, text the reason, such as No Product ID specified. Retrying cannot help. |
PersonyzeException.Transport |
No answer to act on. kind says why: OFFLINE, CONNECTION, TIMEOUT, SERVER, RATE_LIMITED (the account's tracking is paused; the SDK waits 10 minutes before asking again), MALFORMED_RESPONSE. status is the HTTP status, when there was one. |
PersonyzeException.Delivery |
Events were dropped rather than sent. commands lists them, and reason says why: AMBIGUOUS (the request may have reached Personyze, so it is not sent twice), INTERRUPTED (the app stopped while it was being sent), EXPIRED (it waited more than a day for a network), OTHER_VISITOR, OTHER_SESSION, OVERFLOW (too many were waiting), REFUSED. |
PersonyzeException.Invalid |
The SDK refused a call before sending it, such as a blank product id. |
PersonyzeErrorListener
Receives every failure the SDK absorbs, on a background thread:
fun interface PersonyzeErrorListener
{ fun onError(error: PersonyzeException, context: PersonyzeErrorContext)
}
PersonyzeErrorContext says where it happened: operation (navigate, refresh, flush, metadata, notifications, verdict or track), and how many events were deferred (kept to send later) or dropped.