Basic integration with SwiftUI

iOS Classic - Basic integration with SwiftUI

📍

This page describes how to integrate Taboola iOS Classic when using SwiftUI.

While reading the documentation, take a look at our Sample App.

Initialize Taboola

In your SwiftUI app's main struct, create a TBLPublisherInfo object and initialize Taboola:

import SwiftUI
import TaboolaSDK

@main
struct YourApp: App {
    init() {
        // Initialize a TBLPublisherInfo instance with your unique 'publisherName' and 'appStoreId':
        let publisherInfo = TBLPublisherInfo(publisherName: "<publisherName>", appStoreId: <appStoreId>)
        
        // Initialize Taboola for your application:
        Taboola.initWith(publisherInfo)
        
        // (Optional) Set *global* feature flags:
        Taboola.setGlobalExtraProperties(["<feature flag key>":"<value>"])
        
        // (Optional) Set the desired log level:
        Taboola.setLogLevel(.LogLevelDebug)
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
📘

Params

  • publisherName - An alphanumeric string, provided by Taboola - e.g. "sdk-tester-demo".

    This field is also referred to as the Publisher ID.

  • appStoreId - Your App Store ID, obtained via the App Store Connect dashboard.

    See below.

📘

appStoreId

Your App Store ID - aka Apple ID or iTunes ID - is a unique, numeric identifier that allows Apple to distinguish your app from others.

Passing the appStoreId param allows for improved tracking and attribution and is strongly recommended.

📘

Obtaining your App Store ID

  1. Log in to the App Store Connect dashboard.
  2. Under My Apps, select the relevant app.
  3. Under General, select App Information (left).
  4. Copy your Apple ID (right).
🚧

Initialize Taboola in your app's init() method - or as early as possible within the app lifecycle.

Build Taboola content instances

  1. Import the required modules:
import SwiftUI
import TaboolaSDK
import TaboolaSDK_SwiftUI_Umbrella
  1. 📘 What the umbrella provides

    Importing TaboolaSDK_SwiftUI_Umbrella gives you the building blocks for the page wrapper — СlassicPageWrappable, UnitCoordinator, the @Weak property wrapper, and ReusableViewsQueue. You only write your own ClassicPageWrapper class that conforms to СlassicPageWrappable.

    For reference, here is the umbrella surface your wrapper will conform to and route callbacks through. You do not write this code - it ships with the package:

    public protocol СlassicPageWrappable: AnyObject {
        var page: TBLClassicPage! { get }
        var delegates: [UnitCoordinator] { get set }
        var reusableViewsQueue: ReusableViewsQueue<String, TBLClassicUnit> { get }
    }
    
    public protocol UnitProvidable {
        var placement: String { get }
        var height: CGFloat { get set }
    }
    
    public class UnitCoordinator: NSObject {
        public var unit: any UnitProvidable
        public func didLoadWithHeight(height: CGFloat)
    }
    📘

    What each does:

    • СlassicPageWrappable — your page wrapper conforms to this so the umbrella's unit views can find your TBLClassicPage, share a delegate list, and reuse view instances across re-renders.
    • UnitCoordinator — bridges SDK callbacks back to a specific SwiftUI unit. Each unit registers a coordinator into delegates; your didLoadOrResizePlacementName callback filters by placement and forwards the height.
    • UnitProvidable — common shape every umbrella-provided unit type (e.g. ClassicUnitSwiftUI, ClassicDeeperDiveUnitSwiftUI) exposes, so the page wrapper can route generically without per-type code.
  2. Create a page wrapper to manage Taboola content:

class ClassicPageWrapper: NSObject, TBLClassicPageDelegate, СlassicPageWrappable {    
    var page: TBLClassicPage!
    @Weak var delegates: [UnitCoordinator]
    
    let reusableViewsQueue = ReusableViewsQueue<String, TBLClassicUnit>()
    
    init(pageType: String, pageUrl: String) {
        super.init()
        page = TBLClassicPage(pageType: pageType, pageUrl: pageUrl, delegate: self, scrollView: nil)
        page.pageExtraProperties = ["disableScrollIntercept": NSNumber(value: true)]
    }
    
    // MARK: - TBLClassicPageDelegate
    
    func classicUnit(_ classicUnit: UIView!,
                     didLoadOrResizePlacementName placementName: String!,
                     height: CGFloat,
                     placementType: PlacementType) {
        let delegates = delegates.filter { placementName.contains($0.unit.placement) }
        delegates.forEach { $0.didLoadWithHeight(height: height) }
    }
    
    func classicUnit(_ classicUnit: UIView!,
                     didClickPlacementName placementName: String!,
                     itemId: String!,
                     clickUrl: String!,
                     isOrganic organic: Bool,
                     customData: [AnyHashable : Any]!) -> Bool {
        return organic
    }
}
  1. Use the ClassicUnitSwiftUI wrapper in your SwiftUI view:
struct TaboolaView: View {
    let pageWrapper = ClassicPageWrapper(pageType: "article", pageUrl: "https://www.example.com")
    @State var widgetHeight: CGFloat = 0
    
    var body: some View {
        VStack {
            Text("Your content above")
            
            ClassicUnitSwiftUI(pageWrapper: pageWrapper,
                               placement: "Below Article",
                               mode: "alternating-widget-without-video-1x1",
                               height: $widgetHeight)
            .frame(height: widgetHeight)
            
            Text("Your content below")
        }
    }
}
📘

Params

  • pageWrapper - The ClassicPageWrapper instance that manages the Taboola page.
  • placement - The placement name, as provided by Taboola - e.g. "Feed without video".
  • mode - The UI Mode ID of the placement, as provided by Taboola - e.g. "thumbs-feed-01".
  • height - A binding to track the dynamic height of the Taboola content.

A complete example

import SwiftUI
import TaboolaSDK
import TaboolaSDK_SwiftUI_Umbrella

struct TaboolaView: View {
    let pageWrapper = ClassicPageWrapper(pageType: "article", 
                                       pageUrl: "https://www.example.com/articles?id=123")
    @State var widgetHeight: CGFloat = 0
    @State var feedHeight: CGFloat = 0
    
    var body: some View {
        ScrollView {
            VStack {
                Text("Your content above")
                
                ClassicUnitSwiftUI(pageWrapper: pageWrapper,
                                   placement: "Below Article",
                                   mode: "alternating-widget-without-video-1x1",
                                   height: $widgetHeight)
                .frame(height: widgetHeight)
                
                Text("Your content in between")
                
                ClassicUnitSwiftUI(pageWrapper: pageWrapper,
                                   placement: "Feed without video",
                                   mode: "thumbs-feed-01",
                                   height: $feedHeight)
                .frame(height: feedHeight)
            }
        }
    }
}
struct ContentView: View {
    var body: some View {
        NavigationView {
            TaboolaView()
                .navigationTitle("My App")
        }
    }
}

Additional examples

👍

See our Sample App for complete implementations using the Taboola SwiftUI Umbrella package:

Guidelines

🚧
  • To maintain a smooth user experience, fetch Taboola content as soon as the view appears.* Do not cache Taboola content. Fetch new content each time the app opens, or the relevant screen is created.* Use the same ClassicPageWrapper instance for multiple placements on the same page to optimize performance.

The click event

You can handle Taboola events by implementing the TBLClassicPageDelegate protocol in your ClassicPageWrapper:

class ClassicPageWrapper: NSObject, TBLClassicPageDelegate, СlassicPageWrappable {
    // ... existing code ...
    
    func classicUnit(_ classicUnit: UIView!, 
                    didClickPlacementName placementName: String!, 
                    itemId: String!, 
                    clickUrl: String!, 
                    isOrganic organic: Bool,
                    customData: [AnyHashable : Any]!) -> Bool {
        // Insert your code here...
        // Return 'false' if you are handling the click event yourself, or 'true' if you want Taboola SDK to handle the click event.
        // Note: you can override the default behavior for *organic* content only.
        return true
    }
}
🚧

You can override the default behavior for organic content only.

📘

For more information, see Event Handling and didClickPlacementName.

Well Done!

You have completed the basic integration steps using the Taboola SwiftUI Umbrella package!

If everything is working smoothly, take a look at the What's Next section below.

🙈

Taboola content not rendering?

  1. Test with the same params as the sample app, and see if those work.
  2. Still stuck? Submit a question in our forum.

What's next?

  1. For handling clicks and other important events, see Event Handling.
  2. To use advanced options while working with the Taboola SDK, see Advanced Options.
  3. In order to provide personalized recommendations for impressions in the EU and California, make sure to implement GDPR & CCPA respectively.
  4. If you have not already done so, make sure to look at our sample app.
  5. Once you are complete, submit your text app to Taboola for verification - see: App Verification.
🚧

IMPORTANT

Prior to launch, you must provide Taboola with a test app for verification. Skipping this step may result in a significant loss of revenue.

See: App Verification