Skip to content

iOS Rewarded Video Ad Integration

Overview

Rewarded video ads require users to watch the complete video to receive a reward, offering a good user experience and high eCPM. The SDK has built-in countdown and skip control logic, so developers only need to focus on the reward timing.

Integration Steps

1. Create and Load Rewarded Video

swift
import UIKit
import UjuAdCore

final class RewardAdHelper {
    private var rewardAd: UjuAdObject?

    func load(vc: UIViewController) {
        // 激励视频建议传入 userId,用于服务端发奖校验
        let config = UjuAdConfig(
            placementId: "YOUR_REWARD_PLACEMENT_ID",
            userId: "USER_123"
        )
        let reward = UjuAdObject.getRewardObject(vc, config: config)
        reward.setAdObjectListener(RewardListener())
        self.rewardAd = reward
        reward.load()
    }

    func show(vc: UIViewController) {
        // 展示前判断 isReady
        if rewardAd?.isReady() == true {
            rewardAd?.show(vc)
        }
    }

    func destroy() {
        rewardAd?.destroy()
        rewardAd = nil
    }
}

2. Implement Rewarded Video Listener

swift
final class RewardListener: RewardAdObjectListener, @unchecked Sendable {
    func onLoadSuccess() {
        // 广告加载成功,可启用"展示广告"按钮
    }

    func onLoadError(error: UjuException) {
        print("激励视频加载失败: \(error.description)")
    }

    func onAdShow() {
        // 广告开始展示
    }

    func onAdClicked() {
        // 广告被点击
    }

    func onAdClosed() {
        // 广告关闭,恢复 App 交互
    }

    func onAdRewardArrived() {
        // ★ 用户获得奖励(倒计时归零),在此发放奖励
        print("用户获得奖励!")
    }

    func onAdPlayComplete() {
        // 视频播放完成(不直接等于发奖,以 onAdRewardArrived 为准)
    }

    func onAdSkippedVideo() {
        // 用户跳过视频,奖励取消
        print("用户跳过视频,未获得奖励")
    }

    func onAdError(error: UjuException) {
        print("激励视频展示错误: \(error.description)")
    }
}

onAdRewardArrived Has No Parameters

onAdRewardArrived() has no parameters. If you need to customize reward information, verify it via Server-to-Server (S2S) callback on the server side.

Reward Logic

The reward determination for rewarded video is based on callbacks:

CallbackRewardDescription
onAdRewardArrived()Grant rewardUser watched the complete video (countdown reached zero)
onAdSkippedVideo()No rewardUser skipped the video
onAdPlayComplete()No direct rewardVideo playback completed; use onAdRewardArrived as the authoritative signal

15s Skip Rule

The SDK has built-in rewarded video skip control logic:

  • Skip before 15 seconds: A confirmation dialog appears with two buttons: "Continue Watching" and "Confirm Skip". If the user selects "Confirm Skip", onAdSkippedVideo is triggered (no reward); if "Continue Watching" is selected, playback continues.
  • Skip after 15 seconds: The video closes directly without secondary confirmation and is treated as normal completion (triggers onAdRewardArrived).

Dialog and Playback State

When the skip confirmation dialog is displayed, the SDK automatically pauses video playback and countdown; playback resumes after the dialog is closed (except when "Confirm Skip" is selected). Developers do not need to handle playback pause logic themselves.

userId Pass-through

For rewarded video, it is recommended to pass userId in UjuAdConfig for server-side reward verification (matching user identity during S2S callback):

swift
let config = UjuAdConfig(
    placementId: "YOUR_REWARD_PLACEMENT_ID",
    userId: "USER_123"
)

Best Practices

  1. Preload: Call load() in advance before the scenario where the user might trigger display; only show() is needed at display time
  2. Check before showing: Always check isReady() before calling show()
  3. Reward timing: Only grant rewards in onAdRewardArrived; do not grant rewards in onAdSkippedVideo
  4. Resource release: Call destroy() after the ad is closed
  5. Server-side verification: It is recommended to use S2S callbacks for server-side reward verification to prevent client-side forgery

FAQ

Q: How to determine whether a user deserves a reward?

A: Use the onAdRewardArrived() callback as the authoritative signal. onAdPlayComplete() only indicates that the video playback completed and does not directly equal a reward.

Q: Does the user get a reward if they skip the video?

A: No. If the user skips the video (without meeting the reward requirement), onAdSkippedVideo is triggered and no reward should be granted. Skipping after 15 seconds is treated as normal completion and triggers onAdRewardArrived.

Q: What should I do if rewarded video loading fails?

A: Notify the user in onLoadError; you can fall back to another ad placement or retry with a delay. Error code 102 (noFill) means no fill for this request, which is a normal business response.