iOS SDK reference

The iOS SDK's classes, members, hooks and texts, as its Kotlin sources declare them and Swift sees them. The steps are in the iOS guide. Countdowns, promo codes, polls, quizzes, ratings and reactions are drawn. A visitor’s answers are sent to the API and counted there.

Package and requirements

  • Version 0.1.1. The framework is TaleartSDK.xcframework.zip, attached to a GitHub release of github.com/ido-lempert/Taleart. Add it with Swift Package Manager (a binary target, from the repository's Package.swift), or unzip it and drag the XCFramework into the app target.
  • iOS 15 or later (the minimum of the package). Device (arm64) and simulator on Apple silicon; the build has no Intel simulator slice.
// Xcode: File > Add Package Dependencies, then enter the repository URL.
// Or in a Package.swift:
dependencies: [
    .package(url: "https://github.com/ido-lempert/Taleart", from: "0.1.1"),
],
targets: [
    .target(name: "MyApp", dependencies: [
        .product(name: "TaleartSDK", package: "Taleart"),
    ]),
],

TaleartSdk

object TaleartSdk, used from Swift as TaleartSdk.shared. Kotlin's init is named doInit in Swift.

TaleartSdk members
MemberTypeDefaultMeaning
init(config:)fun (TaleartConfig)(required)Sets the SDK’s configuration for every view. Call it once, in Application.onCreate (Android) or at launch (iOS), before the views show. On iOS it is doInit(config:), as Kotlin’s init is named in Swift.
configTaleartConfigthe defaultsThe configuration in use: the last init, or the defaults.
localeString(read-only)The SDK’s locale: the configured one, else the device’s.
translateTranslate(read-only)The text lookup of the SDK’s configuration.

TaleartConfig

The options of TaleartSdk.doInit(config:), built with TaleartConfig(…) and every argument given. Every field is optional on Android; pass all of them from Swift.

TaleartConfig fields
FieldTypeDefaultMeaning
apiUrlString"" (empty)The TaleArt API origin, such as https://api.example.com. Set it: a native app has no page to take it from, and an empty value shows nothing. A view’s own apiUrl wins.
localeString"" (device locale)The SDK’s locale, BCP 47 such as he-IL. Empty: the device’s locale, then English.
stringsMap<String, Map<String, String>>emptyTexts per locale, keyed by the locale (he-IL, or its language he), then by string key.
stringsForEveryLocaleMap<String, String>emptyTexts for every locale, looked up after the locale’s own.
listenerTaleartListener?nullThe hooks of every view. It runs after a view’s own listener.
externalUserIdString?nullThe viewer’s external user ID, for groups targeted to user lists. Sent with each zone read in its own header (X-TaleArt-External-User-Id, base64url), never in a URL; the API does not keep it. Null sends none.
tagsList<String>emptyThe viewer’s targeting tags. A group whose tags do not pass its rule (any or all of them) is left out on the device; the tags are never sent. Empty: every group shows.
propertiesMap<String, Any?>?null (every group shows)The viewer’s properties: the values a tale group’s audience rule reads (Swift: [String: Any]?). A flat map of name to a String, a number, a Boolean or a List of Strings; pass a date as epoch milliseconds. A name starts with a letter and uses letters, digits, _, . or -, up to 64 characters, and is case-sensitive. At most 50 properties, a string at most 256 characters, a list at most 50 items; an invalid entry is ignored. Null: the app passed none, so every audience rule passes, as with no tags. Set: a group whose rule does not pass is left out on the device, together with its tags, and the properties are never sent (not in a header, a URL or an analytics event). An empty map means the app knows nothing about the viewer: neq, notIn and notExists pass, and every other condition fails.
fallbackFallbackModeFallbackMode.NoneWhat a view shows when its zone fails to load. None: nothing, as before. Message: the translated load.failed text and a load.retry button that reads the zone again. A view’s own fallbackView (Android) or fallbackViewController (iOS) wins over both.
frequencyFrequencyRule?null (no cap)How often a viewer sees a tale group. Once: hide a group after its first view. Daily: at most one view per 24 hours. Weekly: one per 7 days. Count(views): hide after N views, N from 1 to 50. A view is one opening of the viewer on a group, counted only on this device in the SDK’s store, never sent to TaleArt. Groups over the cap leave the display; when none remain, nothing is shown. An out-of-range Count throws IllegalArgumentException when it is built.
analyticsBooleantruefalse turns the SDK’s analytics events off: impression, open, view and click. Per zone they are queued and sent every 5 seconds, when 20 are queued, and when the app goes to the background, in requests of at most 50. A request is retried once; a failure is silent. Each event carries only its type, the group id, the tale id (view and click only) and the time, with the zone key and the anonymous visitor id header. A view’s own setting wins over it.
layoutDirectionString?null (the platform’s direction)`ltr` or `rtl` lays every SDK view out in that direction, whatever the device’s language: the bar’s items and scroll start, the viewer’s progress and tap zones, the banner’s arrows, the poll and rating layouts. Null, or any other value, follows the platform (Hebrew and Arabic are right to left). A promo code and a countdown’s digits stay left to right in both.

TaleartZoneView

A zone's view, the iOS counterpart of <taleart-view>. Create it with TaleartZoneView(apiUrl:zoneKey:) and embed its viewController. Keep the object alive as long as the controller.

TaleartZoneView members
MemberTypeDefaultMeaning
apiUrlString?nilThe API origin. Nil or empty uses the one of TaleartSdk.init.
zoneKeyString(init)The zone’s key, tak_…. Changing it reads the zone again.
viewControllerUIViewController(read-only)The controller that shows the zone. Embed it, and keep the TaleartZoneView alive while you do.
opensViewerBooltrueA tap opens the full-screen viewer, modal. False: you handle the tap in onGroupClick.
onGroupClick((DeliveryTaleGroup) -> Unit)?nilCalled with the tapped group, before the viewer opens.
onError((ZoneResult.Failure) -> Unit)?nilCalled with each failed read. Nothing shows then.
onHeightChange((Double) -> Unit)?nilCalled with the display’s new height in points. Use it to size the container.
heightDouble0 (read-only)The display’s height in points. 0 while nothing shows.
listenerTaleartListener?nilThis view’s hooks. Subclass TaleartListenerBase in Swift.
fallbackViewControllerUIViewController?nilShown in place of the zone when the read fails. Nil: TaleartConfig.fallback decides (nothing, or the message).
fallbackHeightDouble120The height in points of fallbackViewController’s view.
analyticsBool?nilfalse turns this view’s analytics events off; nil follows TaleartConfig.analytics.
properties[String: Any]?nil (the SDK’s)This zone’s viewer properties, replacing TaleartConfig.properties for this zone; nil uses the SDK’s. Setting it reads the zone again at once.
stringsMap<String, Map<String, String>>?nilThis view’s texts per locale, over the SDK’s.
localeString?nilThis view’s locale. Nil uses the SDK’s.
clientDeliveryClientthe shared clientThe client the next read uses.
reloadfunc ()(function)Reads the zone again. The display stays until the new zone arrives.
configurefunc (apiUrl:zoneKey:)(function)Sets the API origin and the zone’s key in one call.

Two functions return a view controller directly, for a zone whose key does not change:

TaleartViewController functions
FunctionReturnsDefaultMeaning
TaleartViewController(apiUrl:zoneKey:)UIViewController(required)A controller that shows the zone. The zone’s lifetime is the controller’s: for a key that changes later, use TaleartZoneView.
TaleartViewController(apiUrl:zoneKey:onGroupClick:)UIViewController(required)As above, and calls onGroupClick with each tapped group before the viewer opens.

TaleartTheme

The project's theme as the native SDK reads it. The fields and their rules are the Web SDK's (see Theme and fonts); a field left out or not valid takes its default.

TaleartTheme fields
FieldTypeDefaultMeaning
ringStyleRingStyleGradientGradient, Solid or None: how the unseen ring is drawn.
ringColorsList<String>three colours1 to 3 colours, #rrggbb.
seenRingColorString#6b7280The ring after a group was viewed.
ringWidthInt21 to 4 dp.
cornerRadiusInt?null0 to 32 dp, or the display’s own.
fontFamilyString?nullA font list, or the host’s.
titleColorString?null#rrggbb, or the host’s text colour.
backgroundColorStringtransparent#rrggbb, or transparent.
accentColorString#ffffffThe viewer’s progress and buttons; its text is white or near-black, by contrast.
colorSchemeColorSchemeAutoAuto follows the device’s light or dark setting; Light and Dark force it.
liveColorString?null#rrggbb for the live badge, or the last ring colour.
successColorString#047857A right quiz answer; lightened on a dark card until it reads at 4.5:1.
errorColorString#b91c1cA wrong quiz answer; lightened on a dark card until it reads at 4.5:1.

Bar settings

The bar display's settings, set in the dashboard on a bar zone's frame. A setting that is missing or not valid takes its default. The layouts, and the settings each one ignores, are described in the guide under Bar layouts.

Bar layouts
LayoutUseIgnored settings
ringThe default. Each cover sits in a gradient ring with its title under it; the ring turns while a group is unseen and stays grey once it is seen.None.
chipA pill per group: a round cover, its title, and a dot while the group is unseen (the seen pill is muted and has no dot). The pills wrap onto more rows.shape. The size sets the cover (28, 32 or 40 dp).
posterA portrait card per group: the cover fills it, with the title and the tale count under a dark scrim, and a segment for each tale along the top.shape and size. The card is 112 by 188 dp and has a fixed corner radius.
stackThe groups overlap in one collapsed pill: up to four round covers and a +N bubble for the rest, with the count of unseen groups beside them. The pill opens the first unseen group.shape, showTitles, alignment and gap. The size sets the covers (40, 48 or 56 dp).
Bar settings
FieldTypeDefaultMeaning
layoutBarLayoutRingring, chip, poster or stack (see Bar layouts). A missing or unknown value is ring.
shapeBarShapeCirclecircle or rounded-square: the ring’s and the cover’s shape.
sizeBarSizeMediumsmall, medium or large: the cover’s size, 48, 64 or 80 dp in a ring.
showTitlesBooleantrueShows each group’s title under its cover.
alignmentBarAlignmentStartstart or center: where the items sit when they do not fill the row.
gapInt12Space between items in dp, from 4 to 24.

The banner display's settings, set in the dashboard on a banner zone's frame. A setting that is missing or not valid takes its default. The variants, and the settings each one ignores, are described in the guide under Banner variants.

Poll views

A poll element's view picks how it is drawn: sticker (the default; a missing or unknown view is a sticker), embed, this-or-that, grid or inline. Each option may carry a color (#rrggbb), used only by this-or-that and grid; without one, the theme's colours are used. The embed header is the strings poll.votes and poll.resultsAfterVote (see String keys). The guide shows each view under Poll views.

The poll views and their option colours
ViewUseOption colour
stickerA small card over the tale (default).Not used.
embedA full-width card with its own results header (the vote total, or the hint before a vote).Not used.
this-or-thatTwo halves split at the vote's share, with a VS mark on the seam.Each half: its colour, else the theme's.
gridTwo large tiles with their shares.Each tile: its colour, else the theme's.
inlineCompact rows, in the flow of a page.Not used.

TaleartListener and TaleartListenerBase

The hooks. In Swift, subclass TaleartListenerBase (an open class whose methods do nothing) and override the hooks you need; a protocol cannot inherit those defaults. A hook that throws is logged, and the SDK goes on. The view's listener runs first, then the SDK's.

TaleartListener methods
MethodWhen it firesPayloadCan handle
onLoadedThe zone was read and its display is rendered, or none is needed.event (zoneKeyPrefix, zoneSlug)Nothing to return.
onLoadFailedThe zone could not be read: a refused key, a network failure or a bad answer.event.error (the message)Nothing to return.
onGroupImpressionA group was seen: its bar item was first composed, or a banner slide was first shown in a render. Once per group per load. Native does not measure on-screen visibility, so a group off screen can count too.event.groupNothing to return.
onGroupCappedA group was hidden by the frequency cap (frequency in TaleartConfig) on a load. Once per group per load.event.group, event.ruleNothing to return.
onPresentedThe full-screen viewer opened on a group.event.groupNothing to return.
onDismissedThe viewer closed. event.group is the group it showed last.event.groupNothing to return.
onTaleShownA tale came on screen in the viewer.event.group, event.taleNothing to return.
onActionClickedA call to action was activated, before it opens its URL.event.url, event.newTab (false on native), event.component, event.group, event.taleReturn true when your app routed the link. Return false (the default) and the system browser opens it.
onUserInteractedThe server accepted a visitor’s answer to a poll, a quiz, a rating or a reaction. Once per answer; an answer kept from an earlier visit is not reported again.event.component (type, value: the answer), event.group, event.taleNothing to return.
onComponentEventA component of the tale did something: a countdown reached its end (action ended), a promo code was copied (action copied, component.value the code), or the server accepted an answer (action selected, component.value the answer). The listeners hear it; no analytics event is sent for it.event.component (type, value), event.action, event.group, event.taleNothing to return.
onEventEvery event, after its named method.The eventNothing to return.

TaleartEvent

What each hook receives:

TaleartEvent fields
FieldTypeDefaultMeaning
nameString(required)The hook’s name without “on”, in lower camel case: loaded, loadFailed, groupImpression, groupCapped, presented, dismissed, taleShown, actionClicked, userInteracted, componentEvent.
zoneKeyPrefixString(required)The first 8 characters of the zone key. The whole key is never in an event.
zoneSlugString""The zone’s slug, such as home-top. Empty when the read failed before the zone came.
groupGroupRef?nullThe group: its id, name and position in the zone (from 0).
taleTaleRef?nullThe tale: its id, position in the group (from 0) and title.
componentComponentRef?nullA call to action or a component: its id, its type (button, image-button, swipe-up, countdown, promo-code, poll, quiz, rating, reaction) and its value: a promo code’s code, or a visitor’s answer (a poll’s option id, a quiz’s answer id, a rating’s number from 0 to 100, a reaction’s emoji).
actionString?nullOn componentEvent: what the component did. ended (a countdown reached its end), copied (a promo code was copied) or selected (the server accepted a visitor’s answer). Null for other events.
urlString?nullThe destination of an action that opens one.
newTabBooleanfalseAlways false on native: links open in the system browser.
errorString?nullThe message of a failed load.
ruleFrequencyRule?nullOn groupCapped: the rule the group reached (Once, Daily, Weekly or Count). Null for other events.

String keys

The texts the SDK shows, with the English default of each. Give your own per locale in strings. A value in braces is filled in by the SDK. links.open is native only.

String keys and English defaults
KeyEnglish defaultWhere it shows
viewer.closeCloseThe viewer’s close button.
viewer.playPlayThe viewer’s play button.
viewer.pausePauseThe viewer’s pause button.
viewer.previousTalePrevious taleMoves back one tale.
viewer.nextTaleNext taleMoves on one tale.
viewer.progress{group}, tale {tale} of {count}Announces the position in the viewer.
viewer.taleFallbackTale {number}The name of a tale without a title.
banner.labelBannerThe banner’s name, for screen readers.
banner.carouselcarouselThe banner’s role, for screen readers.
banner.slideslideThe word for one slide.
banner.slideOf{index} of {count}The slide’s position.
banner.previousSlidePrevious slideThe previous-slide control.
banner.nextSlideNext slideThe next-slide control.
banner.showGroupShow {name}A slide’s control, to open its group.
banner.stopRotationStop automatic slide showThe autoplay control, while it plays.
banner.startRotationStart automatic slide showThe autoplay control, while it is paused.
banner.watchWatch storiesThe call to action on a slide.
banner.dismissDismissThe sticky banner’s dismiss button; it hides the banner for the rest of the app’s run.
bar.seen{name}, seenA bar item that the viewer has shown.
bar.loadingLoading storiesThe bar’s loading skeleton, announced while the zone is read.
bar.story{count} storyThe poster layout’s caption for one tale.
bar.stories{count} storiesThe poster layout’s caption for a group’s tales.
bar.newStory{count} new storyThe stack layout’s caption for one unseen group.
bar.newStories{count} new storiesThe stack layout’s caption for the unseen groups.
load.failedStories could not be loaded.The message of a failed read, with fallback = Message.
load.retryTry againThe retry button under the message; it reads the zone again.
links.openOpen in browserNative only: a link that leaves the app for the browser.
countdown.endedEndedThe text a countdown shows at and after its end, when its endedText is left out.
countdown.daysDaysThe unit under a countdown’s days.
countdown.hoursHoursThe unit under a countdown’s hours.
countdown.minutesMinThe unit under a countdown’s minutes.
countdown.secondsSecThe unit under a countdown’s seconds.
promo.copyCopyThe Copy stub of a promo code.
promo.copiedCopiedThe toast after the code reached the clipboard; it clears after four seconds.
promo.copyFailedCould not copy. Select the code and copy it yourself.The status line when the clipboard refused the code.
poll.votedYou voted {label}.The live line after a vote, before the shares.
poll.choseYou chose {label}.The live line after a press in a preview, before the note.
poll.previewNotRecordedVotes are not recorded in the preview.The note after a press in a preview.
poll.failedYour vote could not be sent. Try again.The live line when the vote was refused or could not be sent; the options stay open.
poll.votes{count} votesThe embed view header once voted: the vote total.
poll.resultsAfterVoteResults appear after you voteThe embed view header before a vote.
quiz.answeredYou answered {label}.The live line after an answer to a survey (a quiz without a correct answer).
quiz.rightRight! You answered {label}.The live line when the answer is the correct one.
quiz.wrongAnswerWrong: you answered {label}. The correct answer is {correct}.The live line when the answer is wrong.
quiz.correct correct answerAdded to the name of the correct answer, once answered (screen readers only).
quiz.wrong wrongAdded to the name of the visitor’s wrong answer, once answered (screen readers only).
quiz.previewNotRecordedAnswers are not recorded in the preview.The note after a press in a preview.
quiz.failedYour answer could not be sent. Try again.The live line when the answer was refused or could not be sent; the answers stay open.
rating.sliderLabelYour ratingThe slider’s name, for screen readers.
rating.valueText{value} out of {max}The slider’s value before it is rated.
rating.ratedValueTextYou rated {value} out of {max}The slider’s value once rated.
rating.sendSend ratingThe screen-reader action that sends the slider’s value (double-tap), and the Web SDK’s hidden send button.
rating.sentYou rated {value}.The live line after a rating, before the summary.
rating.previewRatedYou rated {value}. Ratings are not recorded in the preview.The live line after a release in a preview.
rating.failedYour rating could not be sent. Try again.The live line when the rating was refused or could not be sent; the slider stays open.
rating.summaryAverage {average} from {total} {count}The count and average once rated.
rating.singularratingThe word for one rating, in the summary.
rating.pluralratingsThe word for several ratings, in the summary.
reaction.countReactions: {count}Each emoji’s count, read by screen readers once a reaction is tapped.
reaction.failedYour reaction could not be sent. Try again.The live line when the reaction was refused or could not be sent; the emoji stay open.

Web, Android and iOS side by side

The same SDK in each platform. The Web SDK's page is Install a zone.

Web, Android and iOS side by side
TopicWebAndroidiOS
Init (once, for every view)Taleart.init({ … }), or init() from the script’s URLTaleartSdk.init(TaleartConfig(…)) in Application.onCreateTaleartSdk.shared.doInit(config: TaleartConfig(…)) at launch
Zone keyzone-key="tak_…" on <taleart-view>app:taleartZoneKey in XML, zoneKey = in TaleartZoneTaleartZoneView(apiUrl:zoneKey:)
API originapi-url (default: the script’s origin)app:taleartApiUrl; apiUrl in init (required)apiUrl: in TaleartZoneView; apiUrl in init (required)
Localelocale attribute, init({ locale }), else the page’s langTaleartConfig.locale, else TaleartView.locale or TaleartZone(locale =)TaleartConfig(locale:), else zone.locale
Stringsinit({ strings }) or the element’s strings propertyTaleartConfig.strings and stringsForEveryLocale; TaleartView.strings; TaleartZone(strings =)TaleartConfig(strings:, stringsForEveryLocale:); zone.strings
Hooksinit({ hooks }) or the element’s hooks propertyTaleartConfig.listener, or TaleartView.listener, or TaleartZone(listener =)TaleartConfig(listener:) or zone.listener; subclass TaleartListenerBase
Action override (route the link yourself)hooks.onActionClicked: e.preventDefault()onActionClicked returns trueoverride onActionClicked and return true
Tap opens the viewerBuilt in; the onPresented hook firesopensViewer = false, then onGroupClickListeneropensViewer = false, then onGroupClick
External user ID and tagssetExternalUserId(), setTags(), or init()TaleartConfig.externalUserId (sent in a header) and tags (applied on the device)TaleartConfig(externalUserId:, tags:): the same as Android
Fallback when the zone failsfallback="message" or init({ fallback }); a slot="fallback" childTaleartConfig.fallback; TaleartView.fallbackView; TaleartZone(fallback =)TaleartConfig(fallback:); zone.fallbackViewController and fallbackHeight
Viewer propertiesinit({ properties }), setProperties(), setProperty(name, value)TaleartConfig.properties; TaleartView.properties (per view; no XML attribute)TaleartConfig(properties:); zone.properties (per zone)
Frequency capfrequency attribute or init({ frequency })TaleartConfig.frequencyTaleartConfig(frequency:)
Analytics eventsanalytics="off" or init({ analytics: false })TaleartConfig.analytics; app:taleartAnalytics; TaleartZone(analytics =)TaleartConfig(analytics:); zone.analytics

Not available natively yet

  • onGroupImpression counts a group when it is first shown in a render, not when it is on screen: the native SDK does not measure visibility yet.
  • The Compose TaleartZone has no properties parameter: a composable uses the SDK’s viewer properties from TaleartConfig, and cannot set its own for one zone.