Integrating the Uptick iOS SDK

The Uptick iOS SDK renders Uptick offers natively in your Swift app. It supports the same features as the Android SDK :

  • Popup and inline offers: A popup offer is shown in a dimmed overlay on top of your screen. An inline offer is shown in your layout, where you place it.
  • Placements: sdk_order_confirmation (popup) and sdk_order_status (inline). See Placements .
  • Offer callbacks: Your app is told when each offer is received, viewed, accepted and rejected.
  • Error reporting: A callback for logging failures.
  • Colors: Override the default colors to match your app.
  • Dark mode: Offers can follow the device’s dark mode. See Dark Mode .

Requirements

  • iOS: 15.0 or later
  • Swift Package Manager

Installation

  1. Open your project in Xcode.
  2. In the project navigator, select your project file.
  3. In the project editor, select your app’s project under PROJECT.
  4. Go to the Package Dependencies tab.
  5. Click the + button at the bottom of the Package Dependencies section.
  6. In the search bar, paste the Uptick SDK GitHub repository URL: https://github.com/uptick-ads/uptick-ios
  7. Set Dependency Rule to Up to Next Major Version from 1.3.0 and press Add Package.
  8. Assign the UptickSDK package product to your app target.

Placements

Each screen that shows offers needs a placement in the Uptick dashboard, and your app passes the matching value when it starts the offer flow.

Placement Screen Render type
sdk_order_confirmation The screen shown right after the order is placed popup
sdk_order_status An order status or order details screen inline

The placement’s configuration in the dashboard decides whether its offers render as a popup or inline. The SDK reads the render type from the flow, so the same code handles both.

Usage

1. Add an UptickAdView

Create an UptickAdView and add it to your screen where an inline offer belongs. We recommend a UIStackView, so the view takes the offer’s height and the content below it moves down.

import UIKit
import UptickSDK

class OrderConfirmationViewController: UIViewController {
    let uptickAdView = UptickAdView()

    override func viewDidLoad() {
        super.viewDidLoad()

        let titleLabel = UILabel()
        titleLabel.text = "Thanks for your order!"

        let stackView = UIStackView(arrangedSubviews: [titleLabel, uptickAdView])
        stackView.axis = .vertical
        stackView.spacing = 12
        stackView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stackView)

        NSLayoutConstraint.activate([
            stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16),
            stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16)
        ])
    }
}

The view stays hidden until an offer is ready.

2. Start the Offer Flow

Call activateAd(in:withID:siteUrl:parameters:) to start the offer flow.

  • withID: The ID of your integration.
  • siteUrl: The full URL of your site, including https://, e.g. https://www.example.com/. It is sent as dl on every request, so offers, site targeting and site blocking resolve to your site.
  • parameters: The placement and any other parameters. Pass every value as a String. The parameters are the same as on the web; see the Parameter List .

activateAd throws UptickError.invalidSiteUrl and starts no flow if siteUrl is not a full http(s) URL.

do {
    try UptickManager.shared.activateAd(
        in: uptickAdView,
        withID: "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE",
        siteUrl: "https://www.example.com/",
        parameters: [
            "placement": "sdk_order_confirmation",
            "first_name": "Rebecca",
            "order_id": "12345",
            "total_price": "49.99"
        ]
    )
} catch {
    print("Uptick: \(error.localizedDescription)")
}

activateAd must be called on the main thread.

3. Popup and Inline Offers

You don’t need different code for popup and inline offers.

  • Popup: The SDK moves the UptickAdView into a dimmed overlay over the key window. When the flow ends, it puts the view back in its place in your stack view.
  • Inline: The offer renders in the UptickAdView, where you placed it.

To know which render type a flow uses, set renderType. It is called once per flow, before the first offer, with "popup" or "inline".

UptickManager.shared.renderType = { renderType in
    print("Uptick render type: \(renderType)")
}

Offer Callbacks

Set these closures on UptickManager.shared before you call activateAd.

Callback When it is called
onReceivedOffer An offer is ready to show.
onViewedOffer The offer was shown to the user.
onAcceptedOffer The user accepted the offer.
onRejectedOffer The user rejected the offer.
onDisappearOffer The flow ended: the user closed it or there are no more offers.
let uptick = UptickManager.shared

uptick.onReceivedOffer = { offer in
    print("Received offer \(offer.position ?? 0) of \(offer.total ?? 0): \(offer.frame.width)x\(offer.frame.height)")

    if offer.isLast {
        offer.rejectButton.isHidden = true
    }
}

uptick.onViewedOffer = { offer in
    print("Viewed offer \(offer.id)")
}

uptick.onAcceptedOffer = { offer in
    print("Accepted offer \(offer.id)")
}

uptick.onRejectedOffer = { offer in
    print("Rejected offer \(offer.id)")
}

uptick.onDisappearOffer = {
    // Update your layout now that the offers are gone.
    print("Uptick offers closed")
}

Each offer callback receives an UptickData.Offer:

Property Type Description
id String The ID of the offer.
position Int? The position of the offer in the flow, starting at 1.
total Int? The number of offers in the flow.
isLast Bool true when this is the last offer in the flow.
frame CGRect The bounds of the offer’s view. Use it to size anything around the offer.
rejectButton UIButton The offer’s reject button.

Error Handling

errorMessage is called when the offer flow fails, for example when a request fails or the response can’t be read.

errorMessage is for logging and monitoring only. When an offer fails, the SDK doesn’t show the user an error, and your app shouldn’t either: as on the web, a failed offer simply shows nothing.

UptickManager.shared.errorMessage = { errorText in
    print("Uptick offer failed: \(errorText)")
}

Customizing Colors

Set these properties on UptickManager.shared before you call activateAd.

Property Default Used for
primaryColor Green The accept button and highlighted text. The integration’s highlight color, when set in the dashboard, takes precedence.
secondaryColor Light gray The reject button.
backgroundColor White The offer’s background.
UptickManager.shared.primaryColor = .systemIndigo
UptickManager.shared.secondaryColor = .systemGray5
UptickManager.shared.backgroundColor = .systemBackground

Dark Mode

Uptick turns dark mode on or off for each placement. To have it turned on, contact your Uptick Customer Success representative. Dark mode is only available on templates that support it, and it needs iOS SDK 1.2.0 or later.

  • Dark mode on: The offer follows the device. It is dark when the device is in dark mode, and light otherwise. It updates when the device switches modes.
  • Dark mode off: The offer is always light.

Your app needs no code change.

Uptick sets the offer’s light and dark colors, and from iOS SDK 1.3.0 the SDK reads them from each offer flow, so color updates reach your app without an SDK update. A color you set in Customizing Colors takes precedence and is used as-is in both modes, so use a dynamic color such as .systemBackground if you want it to change with the mode.

To keep offers light in a screen that doesn’t support dark mode, set overrideUserInterfaceStyle on the UptickAdView before you call activateAd. The SDK keeps your setting.

uptickAdView.overrideUserInterfaceStyle = .light

Example

A complete order confirmation screen:

import UIKit
import UptickSDK

class OrderConfirmationViewController: UIViewController {
    let uptickAdView = UptickAdView()

    override func viewDidLoad() {
        super.viewDidLoad()

        let titleLabel = UILabel()
        titleLabel.text = "Thanks for your order!"

        let stackView = UIStackView(arrangedSubviews: [titleLabel, uptickAdView])
        stackView.axis = .vertical
        stackView.spacing = 12
        stackView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stackView)

        NSLayoutConstraint.activate([
            stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16),
            stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16)
        ])

        let uptick = UptickManager.shared
        uptick.errorMessage = { errorText in
            // Log only; don't show the user an error for a failed offer.
            print("Uptick offer failed: \(errorText)")
        }
        uptick.onDisappearOffer = {
            print("Uptick offers closed")
        }

        do {
            try uptick.activateAd(
                in: uptickAdView,
                withID: "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE",
                siteUrl: "https://www.example.com/",
                parameters: ["placement": "sdk_order_confirmation", "first_name": "Rebecca"]
            )
        } catch {
            print("Uptick: \(error.localizedDescription)")
        }
    }
}

For an inline offer on an order status screen, use the same code with "placement": "sdk_order_status".

Troubleshooting

  • No offer appears: Confirm the integration ID, that the placement you pass exists in the dashboard, and that siteUrl is your site’s full URL. Check errorMessage for failures.
  • Layout issues: Put the UptickAdView in a UIStackView so it can grow to the offer’s height.
  • Support: If issues persist, reach out to our technical support team for further assistance.