Integrating the Uptick Android SDK

The Uptick Android SDK renders Uptick offers natively in your Kotlin app. It supports the same features as the iOS 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.

Requirements

  • Android: API level 26 (Android 8.0 Oreo) or later
  • Gradle

Installation

Add the Uptick Maven repository to your settings.gradle:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven {
            url "https://sdk.uptick.com/maven"
        }
    }
}

Add the dependency to your app-level build.gradle:

dependencies {
    implementation 'com.uptick:uptick-android:1.1.5'
}

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 Placement value Screen Render type
sdk_order_confirmation Placement.SDK_ORDER_CONFIRMATION The screen shown right after the order is placed popup
sdk_order_status Placement.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 and tells your app through onRenderTypeReceived, so the same code handles both.

Usage

1. Add the Containers

Add two FrameLayout containers to your layout:

  • uptickPopup hosts popup offers. It covers the whole screen and sits above your content; the SDK draws the dimmed overlay inside it.
  • uptickInline hosts inline offers, where an inline offer belongs in your content.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="16dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Thanks for your order!" />

        <FrameLayout
            android:id="@+id/uptickInline"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <FrameLayout
        android:id="@+id/uptickPopup"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

2. Create an UptickManager

Create an UptickManager and a FrameLayout for the SDK to render into. Keep both for the life of the screen.

val uptickManager = UptickManager()
val uptickView = FrameLayout(this)

3. Place Popup and Inline Offers

onRenderTypeReceived is called on the main thread before each offer is shown. Its RenderTypeInfo has the renderType, "popup" or "inline". Move uptickView into the matching container:

uptickManager.onRenderTypeReceived = { info ->
    (uptickView.parent as? ViewGroup)?.removeView(uptickView)
    if (info.renderType == "popup") {
        findViewById<FrameLayout>(R.id.uptickPopup).addView(uptickView)
    } else {
        findViewById<FrameLayout>(R.id.uptickInline).addView(uptickView)
    }
}

When the flow ends, because the user closed it or there are no more offers, the SDK removes the offer from uptickView.

4. Start the Offer Flow

Call initiateView to start the offer flow.

  • integrationId: 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.
  • placement: The Placement for this screen. See Placements .
  • optionalParams: Any other parameters. They are the same as on the web; see the Parameter List .

initiateView throws an IllegalArgumentException and starts no flow if siteUrl is not a full http(s) URL.

import com.uptick.sdk.v1.model.Placement

uptickManager.initiateView(
    context = this,
    container = uptickView,
    integrationId = "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE",
    siteUrl = "https://www.example.com/",
    placement = Placement.SDK_ORDER_CONFIRMATION,
    optionalParams = mapOf(
        "first_name" to "Rebecca",
        "order_id" to "12345",
        "total_price" to "49.99"
    )
)

Offer Callbacks

Set these callbacks on uptickManager before you call initiateView. They are called on the main thread.

Callback When it is called
onOfferReceived An offer is ready to show.
onOfferViewed The offer was shown to the user.
onOfferAccepted The user accepted the offer.
onOfferRejected The user rejected the offer.
uptickManager.onOfferReceived = { offer ->
    Log.d("Uptick", "Received offer ${offer.position} of ${offer.total}")
}

uptickManager.onOfferViewed = { offer ->
    Log.d("Uptick", "Viewed offer ${offer.id}")
}

uptickManager.onOfferAccepted = { offer ->
    Log.d("Uptick", "Accepted offer ${offer.id}")
}

uptickManager.onOfferRejected = { offer ->
    Log.d("Uptick", "Rejected offer ${offer.id}")
}

Each offer callback receives an UptickDataModel:

Property Type Description
id String The ID of the offer.
position String The position of the offer in the flow, starting at 1.
total String The number of offers in the flow.

Error Handling

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

onError 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.onError = { errorMessage ->
    Log.w("Uptick", "Offer failed: $errorMessage")
}

Customizing Colors

Set these properties on uptickManager before you call initiateView. Each takes a color Int.

Property Default Used for
primaryColor Green (#5bb85d) The accept button and highlighted text. The integration’s highlight color, when set in the dashboard, takes precedence.
secondaryColor Light gray (#efefef) The reject button, borders and other secondary elements.
cardBgColor White The offer’s background.
bgColor Semi-transparent black (#4D000000) The dimmed overlay behind a popup offer.
unselectedDigitColor Light gray (#efefef) The progress indicator’s inactive steps.
uptickManager.primaryColor = Color.parseColor("#4f46e5")
uptickManager.secondaryColor = Color.parseColor("#e5e7eb")
uptickManager.cardBgColor = Color.WHITE

Example

A complete order confirmation activity, using the layout from step 1:

import android.os.Bundle
import android.util.Log
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import com.uptick.sdk.apputils.UptickManager
import com.uptick.sdk.v1.model.Placement

class OrderConfirmationActivity : AppCompatActivity() {
    private val uptickManager = UptickManager()
    private lateinit var uptickView: FrameLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_order_confirmation)

        uptickView = FrameLayout(this)

        uptickManager.onRenderTypeReceived = { info ->
            (uptickView.parent as? ViewGroup)?.removeView(uptickView)
            if (info.renderType == "popup") {
                findViewById<FrameLayout>(R.id.uptickPopup).addView(uptickView)
            } else {
                findViewById<FrameLayout>(R.id.uptickInline).addView(uptickView)
            }
        }

        uptickManager.onError = { errorMessage ->
            // Log only; don't show the user an error for a failed offer.
            Log.w("Uptick", "Offer failed: $errorMessage")
        }

        uptickManager.initiateView(
            context = this,
            container = uptickView,
            integrationId = "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE",
            siteUrl = "https://www.example.com/",
            placement = Placement.SDK_ORDER_CONFIRMATION,
            optionalParams = mapOf("first_name" to "Rebecca")
        )
    }
}

For an inline offer on an order status screen, use the same code with placement = 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 onError for failures.
  • Popup is clipped or behind your content: The popup container must cover the whole screen and be the last child of the root layout, so it draws above your content.
  • Support: If issues persist, reach out to our technical support team for further assistance.