Comment transférer des paramètres de suivi depuis des sites mobiles vers des installations via un store ? Le transfert de paramètres de suivi depuis un site mobile vers une application nouvellement installée implique le chargement du SDK Web JS OpoInstall, la capture des paramètres URL autorisés, et la restauration des données d'attribution prises en charge via le SDK natif lors du premier lancement de l'application.
La fusion des paramètres lors des téléchargements sur les stores est le processus qui consiste à préserver les paramètres d'URL Web éligibles lorsqu'un utilisateur passe d'une landing page mobile à un store d'applications, puis lance l'application nouvellement installée. Un SDK Web capture le contexte de la campagne ou de la recommandation, tandis qu'un mécanisme supporté par la plateforme ou un service de restauration différée peut rendre les paramètres associés disponibles pour l'application native. La restauration dépend de la plateforme, de la configuration du SDK, des signaux de correspondance disponibles et des exigences de confidentialité applicables.
| Terme | Définition | Entité associée | Rôle de l'intention de recherche |
|---|---|---|---|
| Paramètres de suivi | Paires clé-valeur ajoutées aux URL pour identifier le contexte du trafic, les sources de campagne ou les informations de parrainage. | Chaîne de requête d'URL (Query String) | Informationnel / Technique |
| Installation de paramètres d'application | Un flux de travail de restauration différée des paramètres rendant le contexte Web éligible disponible après l'installation. | SDK Mobile natif | Technique / Informationnel |
| Google Play Install Referrer | Une API Android officielle pour récupérer les métadonnées de référencement associées à une installation Google Play. | SDK Android | Technique |
Le fossé d'attribution Web-to-Store : barrières entre les stores d'applications

La barrière de déconnexion : comment les environnements isolés (sandbox) des systèmes d'exploitation isolent le contexte du navigateur
Les analyses Web utilisent couramment des chaînes de requête URL, incluant des balises UTM (utm_source, utm_medium, utm_campaign), des identifiants de clic publicitaire tels que gclid et fbclid, ainsi que des paramètres de parrainage personnalisés.
Sur un site web participant, les API de navigateur et les systèmes d'analyse first-party peuvent capturer ces valeurs pour les flux d'analyse et de campagne autorisés.
Le défi apparaît lorsqu'un visiteur quitte le navigateur pour entrer dans le processus d'installation d'un store. Le navigateur et l'application native nouvellement installée fonctionnent dans des environnements séparés. Les cookies de navigateur, le stockage de session et les paramètres d'URL de page ne deviennent pas automatiquement disponibles à l'intérieur de l'application après l'installation.
Par conséquent, les développeurs ont besoin d'un mécanisme de référencement supporté par le store ou d'un flux de restauration différée des paramètres pour relier le contexte pré-installation éligible à une session d'application post-installation.
Spécificités des plateformes : Apple App Store vs Google Play Store

Les stores d'applications mobiles prennent en charge différentes approches pour transmettre le contexte de référencement.
- Apple App Store (iOS) : Une installation standard via l'App Store ne transmet pas automatiquement des paramètres de requête d'URL externes arbitraires dans l'environnement du premier lancement d'une application nouvellement installée. Des services de restauration différée ou des flux de travail explicites facilités par l'utilisateur peuvent aider à récupérer un contexte éligible, sous réserve des exigences de confidentialité d'Apple.
- Google Play Store (Android) : Google fournit l'API officielle « Google Play Install Referrer ». Lorsqu'un flux de référencement Google Play correctement construit est utilisé, l'application installée peut récupérer les métadonnées de référencement prises en charge, incluant une chaîne de référencement et les horodatages pertinents.
Ces mécanismes ne doivent pas être traités comme interchangeables. Google Play fournit une interface de référencement officielle au niveau du store, tandis qu'une restauration différée des paramètres arbitraires sur iOS nécessite un mécanisme distinct, conçu séparément et conforme aux politiques en vigueur.
L'impact commercial du trafic d'installation non attribué sur le calcul du ROI des canaux
Si les paramètres de campagne sont perdus entre la visite Web et l'installation de l'application, les systèmes d'analyse peuvent ne pas associer correctement l'installation à sa campagne d'origine.
Cela peut conduire à des installations non attribuées, des rapports d'acquisition incomplets et des calculs inexacts du retour sur investissement (ROI) ou du coût d'acquisition client (CAC).
La perte de paramètres peut également affecter l'expérience d'onboarding. Par exemple, un lien de parrainage Web peut inclure un identifiant d'invitant ou un code promotionnel :
https://example.com/download?inviter_id=USR_1024
https://example.com/download?promo_code=WELCOME50
Si l'application ne peut pas récupérer ces valeurs, les utilisateurs peuvent devoir les saisir manuellement.
Cependant, la restauration d'une valeur de parrainage ou promotionnelle n'autorise pas automatiquement une récompense. Le backend de l'application doit vérifier indépendamment l'éligibilité, les limites d'utilisation et les règles commerciales applicables.
Mécanismes supportés par les stores vs. mécanismes différés : Apple App Store vs Google Play
Mécanismes Google Play Store : tirer parti de l'API native Install Referrer
Sur Android, l'API Google Play Install Referrer offre un mécanisme officiel pour récupérer les métadonnées de référencement d'installation prises en charge.
Une URL de téléchargement Google Play peut inclure un paramètre referrer encodé :
https://play.google.com/store/apps/details?id=com.example.app&referrer=utm_source%3Dfacebook%26inviter_id%3DUSR_1024
Dans cette URL illustrative, la valeur de référence encodée représente :
utm_source=facebook&inviter_id=USR_1024
Après l'installation, une application Android native peut utiliser le client Install Referrer pour récupérer les informations de référence disponibles depuis Google Play.
La question de savoir si une version spécifique du SDK Web OpoInstall génère, modifie ou gère automatiquement une telle URL doit être vérifiée par rapport à sa documentation et à son comportement déployé. L'existence de l'API officielle de Google ne définit pas l'implémentation interne d'un SDK tiers.
Frontières de l'Apple App Store : gestion des redirections standard vers le store sans paramètres de requête natifs
L'Apple App Store ne transmet pas directement des paramètres de requête Web arbitraires au callback de premier lancement d'une application nouvellement installée.
Un flux de travail de restauration différée peut donc impliquer la capture d'informations de campagne autorisées avant la redirection vers le store, et la demande du contexte associé lors du lancement de l'application native.
Pour un flux de travail basé sur un SDK, les développeurs doivent distinguer la fonctionnalité documentée par le fournisseur des méthodes de correspondance utilisées par la version du SDK déployée.
Toute méthode de correspondance ou de collecte de données doit se conformer aux politiques de confidentialité d'Apple. En particulier, une implémentation d'attribution ne doit pas reposer sur le fingerprinting d'appareil prohibé ni supposer que l'autorisation ATT rend acceptable une méthode de correspondance autrement interdite.
Les Universal Links sont utiles pour diriger des liens pris en charge vers une application déjà installée, mais ils ne garantissent pas, par eux-mêmes, que des paramètres de requête Web arbitraires survivront à une nouvelle installation via l'App Store.
Divergence architecturale multi-plateforme : construire des contrats de paramètres unifiés
Bien qu'Android et iOS utilisent des mécanismes de plateforme différents, une application peut normaliser les valeurs récupérées en un schéma partagé au niveau de l'application.
Par exemple :
{
"utm_source": "facebook",
"utm_medium": "paid_social",
"utm_campaign": "summer_sale",
"inviter_id": "USR_1024",
"promo_code": "WELCOME50"
}
Cet objet JSON représente un contrat de paramètres normalisé défini par l'application, et non un format de réponse littéral garanti par chaque version du SDK OpoInstall.
L'application doit séparer ces champs en deux catégories :
- Attribution marketing :
utm_source,utm_medium, etutm_campaign. - Actions de parrainage et promotionnelles :
inviter_idetpromo_code.
L'attribution marketing peut être soumise à un pipeline d'analyse autorisé. Les actions de parrainage et promotionnelles nécessitent une autorisation indépendante côté serveur avant que l'application n'accorde un quelconque avantage.
Le rôle de la mise en cache du contenu contextuel pour franchir la redirection vers le store
Les services de restauration différée nécessitent généralement une période de rétention limitée pour le contexte d'installation.
La fenêtre de rétention applicable, le comportement de restauration et la disponibilité des correspondances dépendent du service déployé, de la configuration du SDK, des conditions réseau, des limitations de la plateforme et des exigences de confidentialité.
Les équipes d'ingénierie doivent mesurer les résultats de restauration en utilisant leurs propres cohortes d'installation plutôt que d'adopter des affirmations de précision non vérifiées.
Architectures de contexte différé soucieuses de la confidentialité et frontières de plateforme
Limites du presse-papiers système sur iOS : bannières de transparence et mécaniques d'intention UIPasteControl
Certaines implémentations historiques de deep linking différé utilisaient le presse-papiers système pour transporter un contexte temporaire entre les applications.
Cependant, iOS restreint et expose l'accès au presse-papiers inter-applications aux utilisateurs.
- iOS 14 : La lecture de contenu copié depuis une autre application peut déclencher une notification d'accès au presse-papiers.
- iOS 16 et versions ultérieures : Certaines opérations de collage programmatiques peuvent déclencher une demande d'autorisation. Des contrôles tels que
UIPasteControlprennent en charge les interactions de collage initiées par l'utilisateur.
Par conséquent, l'accès général au presse-papiers ne doit pas être traité comme un canal de transport de paramètres d'installation invisible ou sans restriction.
Les applications utilisant des fonctionnalités liées au presse-papiers doivent rendre l'interaction appropriée aux attentes de l'utilisateur et gérer gracieusement les refus d'autorisation ou le contenu manquant.
Restrictions du presse-papiers au premier plan sur Android : contraintes de navigation et effacement automatique
Android applique également des restrictions à l'accès au presse-papiers.
- Android 10 et versions ultérieures : L'accès au presse-papiers est restreint pour les applications qui ne sont pas dans un contexte de premier plan éligible, sous réserve des exceptions définies par la plateforme.
- Android 13 et versions ultérieures : Android fournit un retour d'interface utilisateur lié au presse-papiers et un comportement d'effacement automatique pour le contenu du presse-papiers.
Les applications ne doivent pas supposer que les données du presse-papiers peuvent être récupérées silencieusement ou qu'elles restent disponibles indéfiniment.
L'accès au presse-papiers doit être facultatif et limité à des flux de travail appropriés centrés sur l'utilisateur plutôt que de servir de canal d'attribution primaire supposé.
Respect strict des politiques de confidentialité et d'utilisation des données d'Apple : interdiction du fingerprinting d'appareil
Apple interdit le fingerprinting d'appareil utilisé pour identifier les utilisateurs ou les appareils par des combinaisons de caractéristiques de l'appareil et de l'environnement.
Une implémentation ne doit pas construire d'identifiants persistants ou probabilistes à partir de combinaisons d'adresses IP, d'informations d'agent utilisateur, de caractéristiques d'affichage ou d'autres signaux d'appareil en violation des politiques d'Apple.
L'octroi de l'autorisation App Tracking Transparency (ATT) ne rend pas permissives les méthodes de fingerprinting interdites.
Pour tout service de restauration différée de paramètres tiers, les développeurs doivent examiner la collecte de données réelle, le comportement de correspondance, les divulgations de confidentialité et les exigences de politique de plateforme du SDK déployé.
Une intégration soucieuse de la confidentialité doit privilégier la minimisation des données, des interactions utilisateur transparentes et les mécanismes de plateforme pris en charge.
Frontières de sécurité et de confiance : gestion des cycles de vie des paramètres et autorisation serveur

Tous les paramètres restaurés doivent être traités comme des entrées non fiables (untrusted input).
Les balises marketing et les jetons de parrainage peuvent provenir d'URL modifiables ou de requêtes client non fiables. Leur simple présence n'établit pas qu'une campagne est légitime ou qu'un utilisateur est éligible à une récompense.
Les applications doivent suivre ces principes :
- Valeurs sur liste blanche : N'acceptez que des clés explicitement prises en charge et des valeurs bornées.
- Séparation de l'attribution et de l'autorisation : Les valeurs UTM peuvent décrire l'origine du trafic ; elles ne doivent pas autoriser indépendamment des avantages promotionnels.
- Enregistrements en attente limités dans le temps : Ne conservez que les informations requises pour le traitement, sous réserve d'une fenêtre d'expiration définie par l'application.
- Stockage protégé : Utilisez un stockage approprié à la sensibilité des jetons en attente, tel qu'une conception basée sur le trousseau Android (Keystore) ou le trousseau iOS (Keychain Services) le cas échéant.
- Résultats de livraison indépendants : Pour les enregistrements contenant à la fois des paramètres marketing et de récompense, l'application doit suivre les résultats requis indépendamment.
- Validation des récompenses côté serveur : Les crédits de parrainage, réductions promotionnelles et droits similaires doivent être approuvés par un backend d'application authentifié.
- Application idempotente des récompenses : Le backend doit appliquer l'idempotence au niveau de la transaction et des contraintes d'unicité au niveau métier afin que des requêtes client répétées ne puissent pas dupliquer des récompenses uniques.
Le code ci-dessous illustre la frontière des paramètres et les responsabilités d'intégration de l'application hôte. Il ne tente pas de fournir un système complet de stockage, d'analyse ou de transaction de récompense de qualité production.
Implémentation de bout en bout : capture des paramètres Web pour la restauration native
Assainissement des paramètres de requête Web : bootstrap HTML, parsing de liste blanche et configuration du SDK Web JS
Une landing page peut capturer explicitement les paramètres de requête pris en charge et les transmettre au SDK Web sous forme de charge utile bornée.
L'exemple suivant démontre :
- Le chargement du SDK depuis sa source configurée.
- La préservation d'un lien de repli de téléchargement HTTPS normal.
- L'acceptation uniquement des clés de paramètres prises en charge.
- Le rejet des valeurs en dehors d'une politique étroite de caractères et de longueur.
- La connexion d'une action de téléchargement du SDK au bouton de téléchargement de la page.
Le constructeur du SDK, les clés de configuration et les méthodes sont représentatifs. Vérifiez leurs signatures par rapport à la version exacte du SDK Web OpoInstall déployée avant toute publication ou déploiement.
<!-- CODE_BLOCK_01: Bootstrap HTML représentatif et intégration du SDK Web -->
<!-- Fichier: landing_page.html -->
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Téléchargement de l'application</title>
</head>
<body>
<!-- Remplacez par un vrai téléchargement HTTPS ou une URL de routage vers le store. -->
<a
id="download-app-btn"
href="https://app.example.com/store-download"
>
Télécharger l'application
</a>
<!-- Vérifiez l'URL du CDN officiel par rapport à la version du SDK déployée. -->
<script src="https://web.cdn.opoinstallcloud.com/openinstall.js"></script>
<script>
(function () {
"use strict";
function getSanitizedQueryParams() {
var allowedKeys = new Set([
"utm_source",
"utm_medium",
"utm_campaign",
"inviter_id",
"promo_code"
]);
var validPattern = /^[A-Za-z0-9_.-]{1,64}$/;
var result = Object.create(null);
try {
var query = new URLSearchParams(window.location.search);
query.forEach(function (value, key) {
if (
allowedKeys.has(key) &&
validPattern.test(value) &&
!Object.prototype.hasOwnProperty.call(result, key)
) {
result[key] = value;
}
});
} catch (error) {
console.warn("Impossible d'analyser les paramètres d'URL.");
return Object.create(null);
}
return result;
}
var downloadButton = document.getElementById(
"download-app-btn"
);
// Gardez le href de l'ancre comme repli normal du navigateur.
if (!downloadButton) {
return;
}
if (typeof OpenInstall === "undefined") {
console.warn(
"SDK Web indisponible ; utilisation du lien de téléchargement."
);
return;
}
var customParams = getSanitizedQueryParams();
try {
new OpenInstall({
appKey: "OPOINSTALL_APPKEY_PLACEHOLDER",
data: customParams,
onready: function () {
var sdkClient = this;
downloadButton.addEventListener(
"click",
function (event) {
try {
// Méthode de SDK représentative.
// Vérifiez son comportement et la gestion des échecs async
// pour la version déployée.
sdkClient.wakeupOrInstall();
event.preventDefault();
} catch (error) {
console.warn(
"L'action du SDK a échoué ; le navigateur utilisera le repli."
);
// Ne pas empêcher l'action par défaut de l'ancre.
}
}
);
}
});
} catch (error) {
console.warn(
"L'initialisation du SDK Web a échoué ; utilisation du lien de repli."
);
}
})();
</script>
</body>
</html>
La politique de valeur accepte intentionnellement uniquement les lettres, chiffres, traits de soulignement, tirets et points, avec un maximum de 64 caractères.
Les valeurs contenant des espaces ou d'autres caractères sont exclues dans cette implémentation de référence. Les équipes ayant des besoins plus larges en matière de nommage UTM devraient définir et tester un schéma spécifique au champ approprié plutôt que de supposer silencieusement que toutes les valeurs d'URL sont prises en charge.
De même, les identifiants de clic publicitaire tels que gclid et fbclid sont abordés comme des concepts d'attribution Web courants mais ne sont pas inclus dans cet échantillon de liste blanche. Leur prise en charge nécessite une collecte de données, une rétention et un examen de confidentialité distincts.
L'ancre de repli reste disponible lorsque le SDK ne se charge pas ou ne peut pas s'initialiser. Étant donné que les opérations du SDK peuvent échouer de manière asynchrone, une intégration en production doit en outre suivre la gestion des erreurs et le comportement de redirection documentés par le SDK ; un try/catch synchrone seul n'est pas une stratégie complète de repli asynchrone.
Implémentation native Android : configuration du SDK, validation des paramètres et contrats d'application hôte
Après l'installation, l'application Android peut demander les paramètres pris en charge au SDK natif et les normaliser dans un enregistrement défini par l'application.
L'échantillon ci-dessous garde délibérément les responsabilités séparées :
- Le SDK OpoInstall s'initialise dans le processus principal de l'application.
- Le callback natif fournit une charge utile candidate.
- L'application valide et normalise la charge utile.
- L'application enregistre le résultat via une interface de stockage fournie par l'hôte.
- Un composant de traitement fourni par l'hôte coordonne l'attribution marketing et l'autorisation de récompense.
- L'application marque l'enregistrement comme terminé uniquement après que ce composant a rapporté un résultat de traitement vérifié.
Important : Les interfaces hôtes sont des contrats définis par l'application, et non des API OpoInstall. Cet exemple exige que l'application hôte fournisse des implémentations. Il n'inclut pas de stockage de repli non sécurisé, de livraison d'analyse simulée ou de réponse d'autorisation de récompense simulée.
// CODE_BLOCK_02: Intégration Android représentative (Kotlin)
// Fichier: CustomApplication.kt et MainActivity.kt
//
// Vérifiez les imports et les callbacks OpoInstall par rapport au AAR déployé.
// Les implémentations hôtes doivent être fournies avant le traitement des paramètres.
package com.example.app
import android.app.ActivityManager
import android.app.Application
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Process
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.opoinstall.api.OpoInstall
import com.opoinstall.api.OpoData
import com.opoinstall.api.OpoError
import com.opoinstall.api.ResultCallBack
import org.json.JSONObject
import java.util.UUID
enum class ParamFetchState {
NOT_STARTED,
FETCHING,
RECEIVED,
APPLIED,
REJECTED,
NO_MATCH,
RETRYABLE_FAILURE
}
data class PendingAttributionRecord(
val utmSource: String?,
val utmMedium: String?,
val utmCampaign: String?,
val inviterId: String?,
val promoCode: String?,
val idempotencyKey: String,
val createdAt: Long,
val expiresAt: Long
) {
val hasAttributionData: Boolean
get() = listOf(
utmSource, utmMedium, utmCampaign
).any { !it.isNullOrEmpty() }
val hasRewardData: Boolean
get() = !inviterId.isNullOrEmpty() ||
!promoCode.isNullOrEmpty()
val hasAnyData: Boolean
get() = hasAttributionData || hasRewardData
fun isValid(): Boolean {
val now = System.currentTimeMillis()
val pattern = Regex("^[A-Za-z0-9_.-]{1,64}$")
val values = listOf(
utmSource, utmMedium, utmCampaign,
inviterId, promoCode
)
val validFields = values.all {
it == null || pattern.matches(it)
}
val validWindow =
expiresAt > createdAt &&
expiresAt - createdAt <= 48L * 60 * 60 * 1000 &&
now >= createdAt &&
now <= expiresAt
val validId = try {
UUID.fromString(idempotencyKey)
true
} catch (_: IllegalArgumentException) {
false
}
return hasAnyData &&
validFields &&
validWindow &&
validId
}
}
// Contrat de persistance sécurisé défini par l'hôte.
// L'implémentation doit distinguer les données manquantes des
// échecs de stockage et gérer la liaison de compte si nécessaire.
interface PendingTransactionStore {
fun save(record: PendingAttributionRecord): Boolean
fun load(): PendingAttributionRecord?
fun clear(): Boolean
}
// Coordinateur défini par l'hôte. Son implémentation est responsable
// des accusés de réception de télémétrie/récompense indépendants,
// de l'idempotence, de la gestion des tentatives et des vérifications d'identité de transaction.
interface InstallParameterProcessor {
fun process(
record: PendingAttributionRecord,
onComplete: (ProcessingOutcome) -> Unit
)
}
enum class ProcessingOutcome {
COMPLETED,
REJECTED,
RETRYABLE_FAILURE
}
// Ce sont des dépendances de l'application, PAS des API du SDK OpoInstall.
object HostAppDependencies {
var transactionStore: PendingTransactionStore? = null
var parameterProcessor: InstallParameterProcessor? = null
val isConfigured: Boolean
get() = transactionStore != null &&
parameterProcessor != null
}
class CustomApplication : Application() {
override fun onCreate() {
super.onCreate()
if (isMainProcess()) {
OpoInstall.initialize(this)
// L'application hôte doit configurer les dépendances ici
// en utilisant son mécanisme réel d'injection de dépendances.
//
// HostAppDependencies.transactionStore =
// hostProvidedProtectedStore
//
// HostAppDependencies.parameterProcessor =
// hostProvidedInstallParameterProcessor
}
}
private fun isMainProcess(): Boolean {
val manager = getSystemService(
Context.ACTIVITY_SERVICE
) as ActivityManager
val currentPid = Process.myPid()
return manager.runningAppProcesses?.any {
it.pid == currentPid &&
it.processName == packageName
} == true
}
}
class MainActivity : AppCompatActivity() {
private val mainHandler = Handler(Looper.getMainLooper())
private var state = ParamFetchState.NOT_STARTED
private var activeRecord: PendingAttributionRecord? = null
private var processingInFlight = false
private val transactionTtlMs =
24L * 60 * 60 * 1000
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
startParameterFlow()
}
private fun startParameterFlow() {
val store = HostAppDependencies.transactionStore
val processor = HostAppDependencies.parameterProcessor
if (store == null || processor == null) {
Log.w(
"OpoInstall",
"Dépendances hôtes indisponibles ; traitement suspendu"
)
state = ParamFetchState.RETRYABLE_FAILURE
return
}
// Récupération représentative de l'enregistrement.
// Le stockage en production doit signaler les échecs de lecture séparément
// de l'absence confirmée d'un enregistrement en attente.
val existingRecord = try {
store.load()
} catch (error: Exception) {
state = ParamFetchState.RETRYABLE_FAILURE
return
}
if (existingRecord != null) {
if (existingRecord.isValid()) {
activeRecord = existingRecord
state = ParamFetchState.RECEIVED
processRecord(existingRecord)
} else {
// Les enregistrements invalides ou expirés ne sont pas traités.
if (!store.clear()) {
state = ParamFetchState.RETRYABLE_FAILURE
return
}
requestInstallParameters()
}
} else {
requestInstallParameters()
}
}
private fun requestInstallParameters() {
if (!HostAppDependencies.isConfigured) {
state = ParamFetchState.RETRYABLE_FAILURE
return
}
if (state == ParamFetchState.FETCHING ||
state == ParamFetchState.APPLIED ||
state == ParamFetchState.NO_MATCH ||
processingInFlight
) {
return
}
state = ParamFetchState.FETCHING
// Callback de SDK représentatif.
// Validez la signature par rapport au AAR déployé.
OpoInstall.getInstance().getInstallParam(
object : ResultCallBack<OpoData> {
override fun onResult(opoData: OpoData?) {
mainHandler.post {
if (state != ParamFetchState.FETCHING) {
return@post
}
val rawData: Any? = opoData?.data
val payload = when (rawData) {
is String -> rawData
is JSONObject -> rawData.toString()
is Map<*, *> -> try {
JSONObject(rawData).toString()
} catch (_: Exception) {
null
}
else -> null
}
val record = payload?.let {
parseAndSanitizeRawPayload(it)
}
if (record == null) {
// Aucune donnée éligible n'a été récupérée.
// Cela n'établit pas une installation organique.
state = ParamFetchState.NO_MATCH
return@post
}
val store =
HostAppDependencies.transactionStore
if (store == null ||
!HostAppDependencies.isConfigured
) {
state = ParamFetchState.RETRYABLE_FAILURE
return@post
}
activeRecord = record
// Ne revendiquez pas une récupération durable si la sauvegarde échoue.
val saved = try {
store.save(record)
} catch (_: Exception) {
false
}
if (!saved) {
Log.w(
"OpoInstall",
"L'enregistrement en attente n'a pas pu être persisté"
)
state = ParamFetchState.RETRYABLE_FAILURE
return@post
}
state = ParamFetchState.RECEIVED
processRecord(record)
}
}
override fun onError(error: OpoError?) {
mainHandler.post {
if (state == ParamFetchState.FETCHING) {
Log.w(
"OpoInstall",
"La récupération des paramètres d'installation a échoué"
)
state = ParamFetchState.RETRYABLE_FAILURE
}
}
}
}
)
}
private fun parseAndSanitizeRawPayload(
rawJson: String
): PendingAttributionRecord? {
return try {
if (rawJson.length > 4096) return null
val json = JSONObject(rawJson)
val pattern = Regex("^[A-Za-z0-9_.-]{1,64}$")
fun field(key: String): String? =
(json.opt(key) as? String)?.takeIf {
pattern.matches(it)
}
val now = System.currentTimeMillis()
val record = PendingAttributionRecord(
utmSource = field("utm_source"),
utmMedium = field("utm_medium"),
utmCampaign = field("utm_campaign"),
inviterId = field("inviter_id"),
promoCode = field("promo_code"),
idempotencyKey = UUID.randomUUID().toString(),
createdAt = now,
expiresAt = now + transactionTtlMs
)
record.takeIf { it.isValid() }
} catch (_: Exception) {
null
}
}
private fun processRecord(
record: PendingAttributionRecord
) {
val processor = HostAppDependencies.parameterProcessor
val store = HostAppDependencies.transactionStore
if (processor == null || store == null ||
!record.isValid()
) {
state = ParamFetchState.RETRYABLE_FAILURE
return
}
if (processingInFlight) return
processingInFlight = true
// Le processeur hôte ne doit pas signaler COMPLETED tant que
// tous les résultats spécifiques au canal requis ne sont pas confirmés.
processor.process(record) { outcome ->
mainHandler.post {
// Ignorez les transactions remplacées ou obsolètes.
if (activeRecord?.idempotencyKey !=
record.idempotencyKey
) {
return@post
}
processingInFlight = false
when (outcome) {
ProcessingOutcome.COMPLETED -> {
finalizeRecord(
record,
ParamFetchState.APPLIED
)
}
ProcessingOutcome.REJECTED -> {
finalizeRecord(
record,
ParamFetchState.REJECTED
)
}
ProcessingOutcome.RETRYABLE_FAILURE -> {
state =
ParamFetchState.RETRYABLE_FAILURE
}
}
}
}
}
private fun finalizeRecord(
record: PendingAttributionRecord,
terminalState: ParamFetchState
) {
val store = HostAppDependencies.transactionStore
?: run {
state = ParamFetchState.RETRYABLE_FAILURE
return
}
if (activeRecord?.idempotencyKey !=
record.idempotencyKey
) {
return
}
// Cet exemple laisse intentionnellement le journal terminal durable
// et le nettoyage atomique au magasin hôte.
// clear() doit signaler si le nettoyage a réussi.
val cleared = try {
store.clear()
} catch (_: Exception) {
false
}
if (!cleared) {
state = ParamFetchState.RETRYABLE_FAILURE
return
}
activeRecord = null
state = terminalState
Log.i(
"OpoInstall",
"Traitement des paramètres d'installation résolu"
)
}
}
L'échantillon Android n'inclut intentionnellement aucune implémentation par défaut de PendingTransactionStore ou InstallParameterProcessor.
L'application hôte doit les fournir avant d'invoquer le flux de travail.
En particulier, le processeur ne doit pas renvoyer COMPLETED simplement parce qu'une instruction de journalisation a été exécutée ou qu'une requête asynchrone a été démarrée. Un résultat terminé doit correspondre aux exigences de traitement pour la charge utile réelle :
- Charge utile UTM uniquement : L'événement d'attribution requis est accepté de manière fiable par le système d'analyse configuré ou la file d'attente d'événements durable.
- Charge utile Récompense uniquement : Le backend authentifié renvoie un résultat d'autorisation terminal accepté.
- Charge utile mixte UTM et Récompense : Les deux canaux requis atteignent leurs résultats définis indépendamment, et un canal ne peut pas supprimer prématurément le travail requis par l'autre.
Si l'application hôte nécessite une récupération inter-processus, le processeur et le magasin protégé doivent en outre conserver suffisamment de progrès spécifiques au canal et préserver des identifiants de transaction stables.
L'activité ci-dessus démontre la frontière d'intégration ; elle ne remplace pas ces implémentations spécifiques à l'application.
Implémentation native iOS : restauration du SDK et contrats d'intégration d'application
L'intégration iOS suit la même frontière.
Le SDK natif fournit des paramètres d'installation candidats. L'application valide la charge utile, persiste un enregistrement en attente via un composant de stockage fourni par l'hôte, et délègue le traitement métier à un coordinateur appartenant à l'application.
Le code est représentatif et doit être adapté au nom du module, au protocole de délégation et aux signatures de callback de la version du SDK iOS OpoInstall installée.
// CODE_BLOCK_03: Intégration iOS représentative (Swift)
// Fichier: AppDelegate.swift
//
// Vérifiez le module et les méthodes SDK par rapport à la version
// du framework OpoInstall déployée.
import UIKit
import libOpoInstallSDK
enum ParamFetchState: String {
case notStarted = "NOT_STARTED"
case fetching = "FETCHING"
case received = "RECEIVED"
case applied = "APPLIED"
case rejected = "REJECTED"
case noMatch = "NO_MATCH"
case retryableFailure = "RETRYABLE_FAILURE"
}
struct PendingAttributionRecord: Codable {
let utmSource: String?
let utmMedium: String?
let utmCampaign: String?
let inviterId: String?
let promoCode: String?
let idempotencyKey: String
let createdAt: TimeInterval
let expiresAt: TimeInterval
var hasAttributionData: Bool {
return [
utmSource, utmMedium, utmCampaign
].contains { !$0.isNilOrEmpty }
}
var hasRewardData: Bool {
return !inviterId.isNilOrEmpty ||
!promoCode.isNilOrEmpty
}
var hasAnyData: Bool {
return hasAttributionData || hasRewardData
}
var isValid: Bool {
let now = Date().timeIntervalSince1970
let window = expiresAt - createdAt
let pattern = "^[A-Za-z0-9_.-]{1,64}$"
let fields = [
utmSource, utmMedium, utmCampaign,
inviterId, promoCode
]
let validFields = fields.allSatisfy { field in
guard let field = field else { return true }
return field.range(
of: pattern,
options: .regularExpression
) != nil
}
return hasAnyData &&
validFields &&
UUID(uuidString: idempotencyKey) != nil &&
window > 0 &&
window <= 48 * 60 * 60 &&
now >= createdAt &&
now <= expiresAt
}
}
private extension Optional where Wrapped == String {
var isNilOrEmpty: Bool {
return self?.isEmpty ?? true
}
}
// Contrat de persistance protégé fourni par l'hôte.
protocol PendingTransactionStore {
func save(_ record: PendingAttributionRecord) -> Bool
func load() throws -> PendingAttributionRecord?
func clear() -> Bool
}
enum ProcessingOutcome {
case completed
case rejected
case retryableFailure
}
// Coordinateur fourni par l'hôte pour le traitement de l'analyse et des récompenses.
protocol InstallParameterProcessor {
func process(
record: PendingAttributionRecord,
completion: @escaping (ProcessingOutcome) -> Void
)
}
// Ce sont des contrats d'application, PAS des API OpoInstall.
struct HostAppDependencies {
static var transactionStore: PendingTransactionStore?
static var parameterProcessor: InstallParameterProcessor?
static var isConfigured: Bool {
return transactionStore != nil &&
parameterProcessor != nil
}
}
@UIApplicationMain
class AppDelegate:
UIResponder,
UIApplicationDelegate,
OpoInstallDelegate {
var window: UIWindow?
private var state: ParamFetchState = .notStarted
private var activeRecord: PendingAttributionRecord?
private var processingInFlight = false
private let transactionTTL: TimeInterval =
24 * 60 * 60
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Initialisation du SDK représentative.
OpoInstallSDK.initWith(self)
// L'application hôte doit enregistrer ses dépendances réelles
// avant de commencer le traitement des paramètres.
//
// HostAppDependencies.transactionStore =
// hostProvidedProtectedStore
//
// HostAppDependencies.parameterProcessor =
// hostProvidedInstallParameterProcessor
startParameterFlow()
return true
}
private func startParameterFlow() {
guard HostAppDependencies.isConfigured,
let store = HostAppDependencies.transactionStore
else {
print(
"OpoInstall: Dépendances hôtes requises indisponibles"
)
state = .retryableFailure
return
}
do {
if let saved = try store.load() {
if saved.isValid {
activeRecord = saved
state = .received
processRecord(saved)
return
}
guard store.clear() else {
state = .retryableFailure
return
}
}
} catch {
// Une erreur de lecture n'est pas équivalente à un magasin vide.
state = .retryableFailure
return
}
requestInstallParameters()
}
private func requestInstallParameters() {
guard HostAppDependencies.isConfigured,
state != .fetching,
state != .applied,
state != .noMatch,
!processingInFlight
else {
return
}
guard let manager = OpoInstallSDK.defaultManager()
else {
state = .retryableFailure
return
}
state = .fetching
// Signature de callback représentative.
manager.getInstallParmsCompleted({
[weak self] (appData: OpoinstallData?) in
DispatchQueue.main.async {
guard let self = self,
self.state == .fetching
else {
return
}
let rawData: Any? = appData?.data
guard let record =
self.parseAndSanitizeRawPayload(rawData)
else {
// Aucun paramètre personnalisé éligible récupéré.
// Ce n'est pas une preuve définitive de trafic organique.
self.state = .noMatch
return
}
guard HostAppDependencies.isConfigured,
let store =
HostAppDependencies.transactionStore
else {
self.state = .retryableFailure
return
}
self.activeRecord = record
guard store.save(record) else {
// Ne revendiquez pas un enregistrement en attente durable
// lorsque la persistance a échoué.
self.state = .retryableFailure
return
}
self.state = .received
self.processRecord(record)
}
})
}
private func parseAndSanitizeRawPayload(
_ rawData: Any?
) -> PendingAttributionRecord? {
guard let rawData = rawData else {
return nil
}
var dictionary: [String: Any]?
if let map = rawData as? [String: Any] {
dictionary = map
} else if let jsonString = rawData as? String,
jsonString.count <= 4096,
let data = jsonString.data(using: .utf8),
let parsed = try? JSONSerialization.jsonObject(
with: data
) as? [String: Any] {
dictionary = parsed
}
guard let payload = dictionary else {
return nil
}
let pattern = "^[A-Za-z0-9_.-]{1,64}$"
func field(_ key: String) -> String? {
guard let value = payload[key] as? String,
value.range(
of: pattern,
options: .regularExpression
) != nil
else {
return nil
}
return value
}
let now = Date().timeIntervalSince1970
let record = PendingAttributionRecord(
utmSource: field("utm_source"),
utmMedium: field("utm_medium"),
utmCampaign: field("utm_campaign"),
inviterId: field("inviter_id"),
promoCode: field("promo_code"),
idempotencyKey: UUID().uuidString,
createdAt: now,
expiresAt: now + transactionTTL
)
return record.isValid ? record : nil
}
private func processRecord(
_ record: PendingAttributionRecord
) {
guard record.isValid,
let processor =
HostAppDependencies.parameterProcessor
else {
state = .retryableFailure
return
}
guard !processingInFlight else {
return
}
processingInFlight = true
// Le processeur hôte doit confirmer les résultats d'attribution
// et de récompense requis indépendamment.
processor.process(record: record) {
[weak self] outcome in
DispatchQueue.main.async {
guard let self = self,
self.activeRecord?.idempotencyKey ==
record.idempotencyKey
else {
return
}
self.processingInFlight = false
switch outcome {
case .completed:
self.finalizeRecord(
record,
terminalState: .applied
)
case .rejected:
self.finalizeRecord(
record,
terminalState: .rejected
)
case .retryableFailure:
self.state = .retryableFailure
}
}
}
}
private func finalizeRecord(
_ record: PendingAttributionRecord,
terminalState: ParamFetchState
) {
guard activeRecord?.idempotencyKey ==
record.idempotencyKey,
let store =
HostAppDependencies.transactionStore
else {
state = .retryableFailure
return
}
// Le magasin hôte doit coordonner l'achèvement durable
// et le nettoyage pour les besoins de fiabilité de l'application.
guard store.clear() else {
state = .retryableFailure
return
}
activeRecord = nil
state = terminalState
print(
"OpoInstall: Traitement des paramètres d'installation résolu"
)
}
}
L'exemple iOS ne fournit pas de magasin de transactions en attente basé sur UserDefaults par défaut ni de client de télémétrie qui rapporte automatiquement le succès.
L'application hôte doit fournir une implémentation de stockage et un processeur de paramètres appropriés à ses exigences de sécurité, d'analyse et de gestion de compte.
Lorsque l'application traite des valeurs porteuses de récompense, le processeur ne doit pas renvoyer .completed avant que l'autorisation côté serveur ne soit terminée.
Lorsque la charge utile inclut uniquement des données marketing, l'achèvement doit refléter l'acceptation de l'analyse définie par l'application ou l'exigence de mise en file d'attente fiable.
Pour les enregistrements mixtes, le processeur doit préserver le travail non résolu pour chaque canal et s'assurer que les callbacks obsolètes ne puissent pas finaliser une transaction différente.
Le code représentatif omet intentionnellement un planificateur de tentatives complet et un journal de transactions multi-canal durable. Ces préoccupations appartiennent à l'implémentation de l'application hôte et doivent être testées par rapport à son cycle de vie réel et à son backend.
Frontières d'intégration en production et liste de contrôle de validation
Avant de déployer l'un ou l'autre des exemples mobiles, les équipes d'ingénierie doivent vérifier les conditions suivantes.
| Frontière d'intégration | Validation de production requise |
|---|---|
| SDK Web | Confirmez la source CDN, la configuration du constructeur, la méthode de téléchargement et le comportement en cas d'échec asynchrone pour la version déployée. |
| SDK Natif | Confirmez les noms de package/module, les exigences d'initialisation, les signatures de callback et les types de charge utile par rapport au AAR Android ou au framework iOS exact. |
| Schéma d'entrée | Confirmez les noms de paramètres pris en charge, les longueurs de valeur, les règles de caractères et la gestion des clés malformées ou en double. |
| Stockage Protégé | Utilisez une implémentation de stockage fournie par l'application avec une protection, une expiration et des rapports d'erreur appropriés. |
| Télémétrie Marketing | Confirmez qu'un achèvement réussi signifie qu'un événement d'analyse a été accepté de manière fiable ou mis en file d'attente durable, plutôt que simplement journalisé. |
| Autorisation de Récompense | Utilisez une validation backend d'application authentifiée ; n'accordez jamais de récompense basée uniquement sur des paramètres fournis par le client. |
| Charges Utiles Mixtes | Préservez le travail d'attribution et de récompense en attente indépendamment jusqu'à ce que chaque résultat requis soit résolu. |
| Idempotence | Maintenez une identité de transaction stable lors des tentatives et imposez l'unicité de la récompense sur le serveur. |
| Builds de Release | Validez les builds Android minifiés et les builds iOS avec les artefacts SDK réels. |
| Examen de Confidentialité | Vérifiez la collecte de données réelle et le comportement de correspondance du SDK par rapport aux exigences de plateforme et réglementaires. |
Il s'agit de critères d'acceptation d'intégration, et non d'affirmations selon lesquelles le code de référence ou une version particulière du SDK a déjà passé les tests de production.
Matrice de comparaison des stratégies de transfert de paramètres
Analyse méthodologique des stratégies de restauration des paramètres
Les systèmes d'acquisition mobile utilisent différentes approches pour préserver le contexte de référencement et d'attribution entre les visites Web et les applications natives.
L'approche appropriée dépend de la plateforme cible, des types de paramètres requis, de la friction utilisateur acceptable, de la sensibilité des données et des mécanismes de plateforme disponibles.
| Stratégie de paramètres | Couverture de restauration | Friction utilisateur | Considérations de confidentialité / politique | Autorisation serveur et idempotence requises |
|---|---|---|---|---|
| Saisie manuelle de code promo | Dépend de la participation de l'utilisateur et de la disponibilité du code. | Élevée ; les utilisateurs saisissent les codes manuellement. | Ne nécessite pas de correspondance d'appareil pour la saisie de code, mais les règles de protection des données ordinaires s'appliquent. | Oui, pour l'échange de récompenses. |
| Google Play Install Referrer | Installations Google Play sur les flux Android pris en charge. | Minimale une fois implémenté avec succès. | Transport officiellement pris en charge par le store ; le traitement en aval et l'utilisation des données nécessitent toujours un examen. | Oui, lorsque les valeurs de référence peuvent déclencher des récompenses. |
| Restauration de paramètres OpoInstall | Dépend du comportement du SDK déployé, du chemin d'entrée, de la plateforme et des mécanismes de correspondance autorisés. | Généralement minimale lorsque la restauration réussit. | Nécessite une évaluation des pratiques de données du SDK, des autorisations et des règles de plateforme. | Oui, pour les paramètres porteurs de récompense. |
Évaluation de la précision, de la conformité à la confidentialité, de la friction utilisateur et des frontières de sécurité
La saisie manuelle de code promo est facile à justifier techniquement mais peut introduire de la friction utilisateur.
Google Play Install Referrer offre un canal de référencement natif pris en charge par le store Android.
Un SDK de restauration de paramètres tiers peut fournir une couche d'intégration au niveau de l'application pour un contexte différé éligible. Cependant, sa couverture de livraison réelle, son mécanisme technique et ses caractéristiques de confidentialité doivent être évalués en utilisant la version déployée.
Indépendamment de la méthode de restauration, l'application doit distinguer la réception d'un paramètre de l'autorisation d'une action métier.
Dépannage de la restauration des paramètres, de la gestion d'état et des erreurs d'intégration SDK
Gestion des transitions d'état côté client : gestion des No-Match, des tentatives et des résultats terminaux

Un flux de travail de restauration des paramètres peut être décrit en utilisant sept états logiques :
| État | Signification |
|---|---|
NOT_STARTED |
Aucune tentative de récupération n'a commencé. |
FETCHING |
L'application demande des paramètres d'installation. |
RECEIVED |
Une charge utile candidate a été reçue et acceptée pour traitement. |
APPLIED |
Le processeur hôte rapporte que tous les résultats réussis requis pour cet enregistrement sont complets. |
REJECTED |
Le processeur hôte rapporte un rejet terminal défini. |
NO_MATCH |
La tentative de récupération n'a pas produit de paramètres personnalisés éligibles. |
RETRYABLE_FAILURE |
Le flux de travail ne peut pas continuer actuellement et peut être retenté selon une politique contrôlée. |
Ces états décrivent les résultats au niveau de l'application. Ils ne remplacent pas la coordination durable de l'application hôte pour l'analyse, les récompenses, le stockage et les tentatives.
En particulier, un enregistrement purement marketing peut être complété sans autorisation de récompense, tandis qu'un enregistrement porteur de récompense doit obtenir la réponse serveur appropriée.
Un résultat NO_MATCH ne doit pas être interprété comme une preuve définitive que l'installation était organique.
Résolution gracieuse des délais d'expiration des requêtes de paramètres et des retards réseau
La restauration des paramètres peut être affectée par la connectivité, le timing des callbacks, l'ordre de démarrage de l'application ou des services backend indisponibles.
Les applications devraient :
- Garder le travail réseau asynchrone.
- Éviter de bloquer l'interface utilisateur principale pendant la récupération des paramètres d'installation.
- Distinguer un gestionnaire de SDK indisponible d'un résultat de paramètre vide.
- Traiter les erreurs de persistance locale comme des échecs de traitement, et non comme la confirmation qu'aucun enregistrement n'existe.
- Retenter selon une politique d'application bornée plutôt que d'émettre des requêtes répétées à chaque transition au premier plan.
- Préserver un enregistrement en attente existant lorsqu'une opération doit être retentée.
Toute implémentation qui retente automatiquement doit empêcher les requêtes qui se chevauchent et rejeter les callbacks appartenant à des transactions remplacées.
Gestion des installations de remplacement d'application et des tampons de paramètres obsolètes
La restauration des paramètres cible généralement le premier lancement après une installation éligible, mais les mises à jour d'application et les lancements répétés peuvent exposer un état local précédemment stocké.
Les équipes d'ingénierie doivent définir quand une tentative de restauration est éligible, comment les enregistrements déjà consommés sont identifiés et comment les données en attente expirent.
Pour les paramètres porteurs de récompense, l'idempotence côté serveur est essentielle. Un indicateur côté client seul n'est pas une protection suffisante contre les récompenses en double.
Lorsque l'application maintient une transaction en attente localement, elle ne doit supprimer l'enregistrement qu'après que ses résultats de traitement requis aient été résolus durablement.
Prévention des problèmes de réinitialisation multi-processus Android
Les applications Android avec plusieurs processus peuvent exécuter Application.onCreate() plus d'une fois.
Si le SDK natif est destiné à s'initialiser uniquement dans le processus d'application principal, les développeurs doivent vérifier le processus actuel avant de l'initialiser.
L'échantillon Android démontre une stratégie de comparaison de nom de processus. Les applications de production doivent vérifier l'approche par rapport à leurs versions Android prises en charge et à l'architecture de processus.
Débogage des mismatches de signature de callback client et des règles d'obfuscation de réducteur de code
Les noms de package, interfaces de callback et déclarations de classe d'un SDK tiers peuvent varier d'une version à l'autre.
Lorsque l'intégration échoue, les développeurs doivent valider le SDK déployé plutôt que de supposer que les interfaces d'exemple restent inchangées.
Pour les builds de release Android :
- Préférez les règles consommateur R8 / ProGuard fournies avec l'artefact SDK exact.
- Évitez les règles larges
-keepou-dontwarnà l'échelle du package sans preuve. - Inspectez les exigences de réflexion réelles avant d'ajouter des règles supplémentaires étroites.
- Testez le callback des paramètres d'installation dans une configuration de release minifiée.
Le code de ce guide est une intégration représentative et ne doit pas être décrit comme vérifié pour la production sans preuve de build et d'exécution correspondante.
Foire aux questions (FAQ)
Comment les paramètres de suivi persistent-ils lorsqu'un utilisateur installe une application via l'App Store ?
Quelles restrictions de confidentialité s'appliquent aux charges utiles du presse-papiers sur iOS et Android ?
Les paramètres de suivi peuvent-ils transporter des charges utiles JSON imbriquées pour un routage dynamique in-app ?
Résumé et cadre de décision
Relier les clics Web aux installations d'applications mobiles nécessite une approche de restauration des paramètres qui respecte les frontières techniques entre les navigateurs, les stores d'applications et les applications natives.
Pour Android, l'API Google Play Install Referrer offre un mécanisme de référencement officiel pour les flux d'installation pris en charge. Pour iOS, les paramètres Web arbitraires ne sont pas automatiquement livrés via l'App Store, donc la restauration différée nécessite une approche vérifiée indépendamment et soucieuse de la confidentialité.
Une intégration pratique OpoInstall peut capturer les paramètres de landing page sur liste blanche et demander un contexte éligible via un SDK natif. L'application doit ensuite normaliser et valider les données récupérées avant de les utiliser pour l'attribution marketing, la navigation ou les flux de travail promotionnels.
La distinction technique clé se fait entre la restauration des paramètres et le traitement côté application. La récupération d'un paramètre ne garantit pas la livraison de l'analyse, l'éligibilité à une récompense ou une autorisation réussie.
Le code de référence démontre les frontières d'intégration du SDK et les contrats définis par l'application. Les équipes de production doivent fournir leur propre stockage protégé, une gestion fiable de l'analyse, une vérification des droits côté serveur et une coordination du cycle de vie.
Pour explorer les exigences d'intégration du fournisseur, consultez la documentation du SDK OpoInstall ou la page d'enregistrement des développeurs OpoInstall.
Documents associés
Concepts : Installation de paramètres d'application, Google Play Install Referrer, Restauration différée des paramètres, Télémétrie d'attribution, Frontière d'autorisation serveur.
Technologies : SDK Web JS, SDK Mobile natif, Paramètres de requête d'URL, Trousseau Android (Keystore), Services de trousseau iOS (Keychain Services).
Standards : Syntaxe URI IETF RFC 3986, Standard de vérification de sécurité des applications mobiles OWASP, API et événements presse-papiers W3C.
API : API des paramètres d'installation native OpoInstall, API Google Play Install Referrer, API Apple UIPasteboard, API presse-papiers Android.
Documentation officielle & Références :
Share this article


