Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
639cfd8
Switch SwiftPM Superscript dependency to superscript-ios-next
anglinb May 5, 2026
3b992d5
Merge pull request #469 from superwall/switch-to-superscript-ios-next
ianrumac May 6, 2026
571bf6e
Add changelog entry
yusuftor May 11, 2026
9bef2a0
Improve Apple Search Ads attribution capture
yusuftor May 13, 2026
3f2c7c3
Fix outer-call cleanup race in AttributionPoster
yusuftor May 13, 2026
ec63850
Don't bookkeep failed attempts on cancellation
yusuftor May 13, 2026
d7902f8
Treat backend error as retryable; document eligible behavior
yusuftor May 13, 2026
10f9d74
Make listenToConfig actually detect off→on toggles
yusuftor May 13, 2026
cae3d67
Drop redundant outer post-side backoff
yusuftor May 13, 2026
733f382
Persist permanent-unsupported sentinel
yusuftor May 13, 2026
90554fa
Close cancellation race between track suspension and task storage
yusuftor May 13, 2026
395c3d1
Add tests for canStartAttempt guards
yusuftor May 13, 2026
7e4f96a
Serialize AdServicesAttributionTests suite
yusuftor May 13, 2026
ad840c4
Drop fictional eligible/error fields from AdServicesResponse
yusuftor May 13, 2026
68f4276
Tighten retry window from 48h to 24h
yusuftor May 14, 2026
b97bfe5
Drop redundant inner [weak self] in listenToConfig sink
yusuftor May 14, 2026
f163b3b
Make ASA attribution install-scoped
yusuftor May 14, 2026
9ad9582
Wire AdServices token migration through V4Migrator
yusuftor May 14, 2026
da17853
Fix and extend migrator tests for V4
yusuftor May 14, 2026
a44acb5
Only blacklist platformNotSupported (drop incorrect internalError check)
yusuftor May 14, 2026
085545f
Propagate cancellation from Task.sleep in fetchTokenWithBackoff
yusuftor May 14, 2026
ede3728
Tighten listenToConfig task priority and isPermanentTokenError scope
yusuftor May 14, 2026
8dbb96c
Update changelog
yusuftor May 14, 2026
90722d8
Pair every analytics .start with a terminal; skip dev simulator path …
yusuftor May 14, 2026
94a618f
Merge pull request #470 from superwall/improve-apple-search-ads-attri…
yusuftor May 14, 2026
1c81ac5
Use non-optional UUID init for zero-IDFA sentinel
yusuftor May 14, 2026
2e2900c
Correct false-positive → false-negative in zero-IDFA comment
yusuftor May 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

The changelog for `SuperwallKit`. Also see the [releases](https://github.com/superwall/Superwall-iOS/releases) on GitHub.

## 4.15.2

### Enhancements

- Improves Apple Search Ads attribution capture rate.
- Filters out the all-zeros IDFA sentinel (returned when App Tracking Transparency is denied) so it no longer pollutes the `idfa` attribute on attribution payloads.

### Fixes

- Changes the Superscript spm package repo source to a new lightweight repo meaning that the download of the package is way faster.

## 4.15.1

### Enhancements
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
### Package Management
- Swift Package Manager: Primary dependency management via `Package.swift`
- CocoaPods: Also supported via `SuperwallKit.podspec`
- Dependencies: `Superscript-iOS` at exact version 1.0.4
- Dependencies: `superscript-ios-next` at exact version 1.0.14 (slim binary-target distribution; replaces the legacy `Superscript-iOS` repo whose committed xcframework bloated clones)

## Architecture Overview

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ let package = Package(
)
],
dependencies: [
.package(url: "https://github.com/superwall/Superscript-iOS", .exact("1.0.13"))
.package(url: "https://github.com/superwall/superscript-ios-next", .exact("1.0.14"))
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "SuperwallKit",
dependencies: [
.product(name: "Superscript", package: "Superscript-iOS")
.product(name: "Superscript", package: "superscript-ios-next")
],
exclude: ["Resources/BundleHelper.swift"],
resources: [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// AdServicesAttributionAttempts.swift
// SuperwallKit
//

import Foundation

struct AdServicesAttributionAttempts: Codable, Equatable {
/// Total attempts that have completed (either at Apple's SDK call or the
/// backend post).
var count: Int
/// When we first tried for this install. Used to bound how long we keep
/// retrying — Apple's attribution data is only useful within ~24h of install.
var firstAttemptDate: Date
var lastAttemptDate: Date
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,41 @@ final class AttributionFetcher {
return nil
}

// When ATT hasn't been authorized iOS returns the all-zeros UUID
// sentinel. Don't pass that through as an IDFA — it pollutes attribution
// payloads with junk that downstream MMPs treat as a real id.
if identifierValue == Self.zeroAdvertisingIdentifier {
return nil
}

return identifierValue.uuidString
}
#endif
return nil
}

// Non-optional construction via `init(uuid:)` — `init(uuidString:)` returns
// an Optional which would make the equality check silently false-negative
// (zero-IDFA passes through unfiltered) if the literal ever failed to parse.
private static let zeroAdvertisingIdentifier = UUID(uuid: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))

/// Whether this build/environment can ever produce an AdServices token.
/// `false` on builds that didn't link AdServices.framework and on debug
/// simulator runs without `SUPERWALL_MOCK_AD_SERVICES_TOKEN`. Lets the
/// poster short-circuit before entering its 23s backoff schedule in
/// development.
var canProduceAdServicesToken: Bool {
#if !canImport(AdServices)
return false
#else
#if targetEnvironment(simulator) && DEBUG
return ProcessInfo.processInfo.environment["SUPERWALL_MOCK_AD_SERVICES_TOKEN"] != nil
#else
return true
#endif
#endif
}

// should match OS availability in https://developer.apple.com/documentation/ad_services
@available(iOS 14.3, tvOS 14.3, macOS 11.1, watchOS 6.2, macCatalyst 14.3, *)
var adServicesToken: String? {
Expand Down
Loading
Loading