https://github.com/dankinsoid/swift-ads
Swift iOS Ads interface
https://github.com/dankinsoid/swift-ads
Last synced: 10 months ago
JSON representation
Swift iOS Ads interface
- Host: GitHub
- URL: https://github.com/dankinsoid/swift-ads
- Owner: dankinsoid
- Created: 2025-07-29T14:24:59.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2025-07-29T15:09:30.000Z (11 months ago)
- Last Synced: 2025-07-29T17:22:13.140Z (11 months ago)
- Language: Swift
- Size: 16.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# SwiftAds
A Swift package that provides a common interface for advertising systems across different platforms and ad networks. Similar to [swift-log](https://github.com/apple/swift-log) and [swift-metrics](https://github.com/apple/swift-metrics), SwiftAds defines a standardized API that allows you to switch between different ad implementations without changing your application code.
## Features
- 🎯 **Unified API** - Single interface for all ad types (banners, interstitials, rewarded videos)
- 🔧 **Pluggable Backends** - Easy integration with any ad network
- 🚀 **Async/Await Support** - Modern Swift concurrency
- 📱 **Cross-Platform** - iOS, macOS, tvOS, watchOS support
- 🎮 **Placement Targeting** - Flexible ad placement management
- 🚫 **NOOP Handler** - Built-in no-operation handler
- 🔄 **Multiplex Handler** - Fallback support with multiple ad networks
## Installation
### Swift Package Manager
Add SwiftAds to your `Package.swift`:
```swift
dependencies: [
.package(url: "https://github.com/dankinsoid/swift-ads.git", from: "1.0.0")
]
```
Or add it through Xcode:
1. File → Add Package Dependencies
2. Enter: `https://github.com/dankinsoid/swift-ads.git`
## Quick Start
### 1. Bootstrap the Ads System
First, configure SwiftAds with your preferred ad handler during app startup:
```swift
import SwiftAds
// Bootstrap with your ad handler (once per app lifecycle)
AdsSystem.bootstrap(YourCustomAdsHandler())
```
### 2. Display Ads
```swift
import SwiftAds
// Create ads instance
let ads = Ads()
// Show interstitial ad
try await ads.showInterstitial(id: "your-ad-id")
// Show rewarded video
try await ads.showRewarderVideo(id: "your-rewarded-ad-id")
// Load and display banner
let bannerView = try await ads.loadBanner(
id: "your-banner-id",
in: viewController,
size: .standart
)
view.addSubview(bannerView)
```
### 3. Preload Ads for Better Performance
```swift
// Preload ads for faster display
try await ads.loadInterstitial(id: "your-ad-id")
try await ads.loadRewarderVideo(id: "your-rewarded-ad-id")
```
## Ad Placements
Use placements to organize and target different ad locations in your app:
```swift
// Create ads instance with placement
let mainMenuAds = Ads(placement: "main_menu")
let gameOverAds = Ads(placement: "game_over")
// Different placements can show different ads
try await mainMenuAds.showInterstitial(id: "menu-ad")
try await gameOverAds.showInterstitial(id: "game-over-ad")
```
## Banner Sizes
SwiftAds supports various banner sizes:
```swift
// Standard banner sizes
let standardBanner = try await ads.loadBanner(id: "banner-id", in: vc, size: .standart)
let mediumBanner = try await ads.loadBanner(id: "banner-id", in: vc, size: .medium)
let largeBanner = try await ads.loadBanner(id: "banner-id", in: vc, size: .large)
// Adaptive banner (adjusts to screen width)
let adaptiveBanner = try await ads.loadBanner(id: "banner-id", in: vc, size: .adaptive)
// Custom size
let customBanner = try await ads.loadBanner(
id: "banner-id",
in: vc,
size: .custom(width: 320, height: 100)
)
```
## Creating Custom Ad Handlers
Implement the `AdsHandler` protocol to integrate with your preferred ad network:
```swift
import SwiftAds
struct MyAdMobHandler: AdsHandler {
func initAds() async throws {
// Initialize your ad network SDK
}
@MainActor
func loadBanner(
in controller: UIViewController,
size: Ads.Size,
id: String,
placement: String?
) async throws -> UIView {
// Return configured banner view
}
func loadInterstitial(id: String, placement: String?) async throws {
// Preload interstitial ad
}
func loadRewarderVideo(id: String, placement: String?) async throws {
// Preload rewarded video ad
}
@MainActor
func showInterstitial(
from controller: UIViewController,
id: String,
placement: String?
) async throws {
// Display interstitial ad
}
@MainActor
func showRewarderVideo(
from controller: UIViewController,
id: String,
placement: String?
) async throws {
// Display rewarded video ad
}
}
// Bootstrap your handler
AdsSystem.bootstrap(MyAdMobHandler())
```
### Example Implementation
For a complete handler implementation example, see:
- [**AppLovinAdsHandler**](https://github.com/dankinsoid/AppLovinAdsHandler) - Full AppLovin integration with SwiftAds
## Multiplex Handler (Fallback Support)
Use `MultiplexAdsHandler` to combine multiple ad networks with automatic fallback:
```swift
import SwiftAds
// Create multiplex handler with fallback priority
let multiplexHandler = MultiplexAdsHandler(
PrimaryAdNetworkHandler(), // Try this first
SecondaryAdNetworkHandler(), // Fallback to this if first fails
NOOPAdsHandler() // Final fallback (always succeeds)
)
// Bootstrap with multiplex handler
AdsSystem.bootstrap(multiplexHandler)
```
The `MultiplexAdsHandler` tries each handler in sequence until one succeeds:
1. **Primary Network**: Attempts to load/show ads with your main provider
2. **Secondary Network**: Falls back if primary fails (network issues, no fill, etc.)
3. **Tertiary/NOOP**: Final fallback to ensure ads never completely break your app
Benefits:
- **Higher Fill Rates**: Multiple networks increase ad availability
- **Redundancy**: App continues working if one network fails
- **Revenue Optimization**: Waterfall approach maximizes monetization
## Exponential Retry Handler
Use `ExponentialRetryAdsHandler` to add automatic retry logic with exponential backoff for **load operations only**:
```swift
import SwiftAds
// Wrap any handler with exponential retry logic
let retryHandler = ExponentialRetryAdsHandler(
wrapping: YourAdNetworkHandler(),
maxRetries: 6 // Default: 6 attempts
)
// Bootstrap with retry handler
AdsSystem.bootstrap(retryHandler)
```
The retry delays follow exponential backoff (only for load functions):
- 1st retry: 2 seconds (2^1)
- 2nd retry: 4 seconds (2^2)
- 3rd retry: 8 seconds (2^3)
- 4th retry: 16 seconds (2^4)
- 5th retry: 32 seconds (2^5)
- 6th retry: 64 seconds (2^6)
**Load Functions with Retry:**
- `loadBanner()` - Retries with exponential backoff
- `loadInterstitial()` - Retries with exponential backoff
- `loadRewarderVideo()` - Retries with exponential backoff
**Show Functions (No Retry):**
- `showInterstitial()` - No retry (immediate success/failure)
- `showRewarderVideo()` - No retry (immediate success/failure)
Benefits:
- **Load Reliability**: Automatically recovers from temporary network issues during ad loading
- **Smart Backoff**: Exponential delays prevent server overload while maximizing success rate
- **Show Performance**: No delays on show operations for immediate user experience
You can combine handlers for powerful retry + fallback patterns:
```swift
let robustHandler = MultiplexAdsHandler(
ExponentialRetryAdsHandler(wrapping: PrimaryAdNetworkHandler()),
ExponentialRetryAdsHandler(wrapping: SecondaryAdNetworkHandler()),
NOOPAdsHandler()
)
AdsSystem.bootstrap(robustHandler)
```
## Testing
For testing and development, use the built-in `NOOPAdsHandler`:
```swift
#if DEBUG
AdsSystem.bootstrap(NOOPAdsHandler())
#endif
```
## Error Handling
SwiftAds methods can throw errors. Handle them appropriately:
```swift
do {
try await ads.showInterstitial(id: "ad-id")
} catch {
print("Failed to show ad: \\(error)")
// Handle error (e.g., no internet, ad not loaded, etc.)
}
```
## Thread Safety
SwiftAds is thread-safe and can be used from any queue. UI-related operations are automatically dispatched to the main actor.
## Related Packages
SwiftAds works great with other Swift ecosystem packages that follow similar interface patterns:
- [**swift-analytics**](https://github.com/dankinsoid/swift-analytics) - Unified analytics interface
- [**swift-remote-configs**](https://github.com/dankinsoid/swift-remote-configs) - Unified remote configuration interface
Example integration:
```swift
import SwiftAds
import SwiftAnalytics
import SwiftRemoteConfigs
// Track ad events
try await ads.showInterstitial(id: "game-over-ad")
Analytics.track("ad_displayed", properties: ["placement": "game_over"])
// Use remote config for ad IDs
let adId = RemoteConfigs.string("interstitial_ad_id", default: "default-ad-id")
try await ads.showInterstitial(id: adId)
// Combine with retry handler
let handler = MyAdNetworkHandler().withExponentialRetry()
AdsSystem.bootstrap(handler)
```
## Requirements
- iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+
- Swift 5.9+
- Xcode 15.0+
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
This project is licensed under the MIT License - see the LICENSE file for details.