Apps mobiles (iOS et Android)
Un module d'un fichier, en Swift ou en Kotlin, qui envoie les ouvertures et les conversions sans identifiant publicitaire.
La requête
POST
https://firstmrr.app/app/api/collectClé publique dans le corps (k)| Champ | Type | Requis | Description |
|---|---|---|---|
k | string | Obligatoire | Ta clé publique. |
e | string | Obligatoire | L'événement : open ou screen (compté comme une visite), signup, activation, trial, payment, cancel, source, ab:exposure, ou un nom à toi. |
a | string | Obligatoire | L'identifiant d'installation : un UUID aléatoire créé au premier lancement. |
p | string | Optionnel | L'écran affiché (/home). |
w | number | Optionnel | La largeur de l'écran en points (tablette à partir de 600). |
v / c / i | number / string / string | Optionnel | Paiement : montant, devise, identifiant de la transaction. |
s / d | string / string | Optionnel | Réponse d'origine et compte cité. |
ab | object[] | Optionnel | Les affectations A/B, [{ "test": "pricing_page", "variant": "b" }], 4 au plus. |
La réponse est toujours 204, sans corps : ne la lis pas et ne réessaie pas. Envoie sans bloquer l'interface, 5 secondes au plus.
Le module
import UIKit
enum FirstMRR {
private static let endpoint = URL(string: "https://firstmrr.app/app/api/collect")!
private static let key = "pk_0123456789abcdef01234567" // your public key
private static let defaults = UserDefaults.standard
/// A random id created at the first launch: never the IDFA or identifierForVendor.
static var installId: String {
if let id = defaults.string(forKey: "firstmrr.installId") { return id }
let id = UUID().uuidString
defaults.set(id, forKey: "firstmrr.installId")
return id
}
/// The "Audience measurement" setting of your app.
static var enabled: Bool {
get { !defaults.bool(forKey: "firstmrr.optOut") }
set { defaults.set(!newValue, forKey: "firstmrr.optOut") }
}
static func track(_ event: String, screen: String = "/", extra: [String: Any] = [:]) {
guard enabled else { return }
var body: [String: Any] = ["k": key, "e": event, "a": installId, "p": screen, "w": Int(UIScreen.main.bounds.width)]
body.merge(extra) { _, new in new }
guard let data = try? JSONSerialization.data(withJSONObject: body) else { return }
var request = URLRequest(url: endpoint, timeoutInterval: 5)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = data
URLSession.shared.dataTask(with: request).resume() // fire and forget: no retry, no queue
}
}
// FirstMRR.track("open", screen: "/home")
// FirstMRR.track("payment", extra: ["v": 9.99, "c": "USD", "i": transaction.id])Appelle track("open") à chaque ouverture et retour au premier plan, signup, activation, trial, puis payment dans le rappel de succès de StoreKit, Google Play Billing, RevenueCat ou Superwall.
Validation Apple et Google
- Pas d'IDFA, d'AAID, d'
identifierForVendorni d'empreinte de l'appareil : pas de fenêtre App Tracking Transparency. - Un réglage « Mesure d'audience », activé par défaut, qui coupe tout envoi.
PrivacyInfo.xcprivacy: Product Interaction et Device ID, non liés à l'identité, sans suivi, finalité Analytics ; Purchase History si tu envoies les paiements ; UserDefaults avec la raison CA92.1.
L'installation assistée de Distribution → Tracking écrit ce module pour toi et te dit quoi déclarer dans App Store Connect et Google Play.