Branch est-il un substitut aux liaisons dynamiques de Firebase?

S’il vous est arrivé de créer quelque chose de plus important qu’une simple application mobile de base, vous vous êtes sûrement trouvé confronté au besoin de disposer d’un back-end. Il est probable que vous ayez alors découvert que la conception et l’entretien de l’un d’entre eux est une tâche ardue. Entrez sur les plates-formes BaaS (back-end en tant que service) telles que Firebase et Parse des plates-formes qui changent la donne pour les développeurs qui veulent se concentrer sur la création d’une application.

Google a acquis Firebase en 2014, et de simple fournisseur de Baas il est devenu une application complète sous forme de plate-forme de service, avec une série de nouveaux outils destinés à la création et au développement d’une application. Pour les développeurs, C’est une nouvelle extraordinaire: il est désormais plus facile que jamais de maintenir un MVP à jour et opérationnel. Dans l’équipe de Branch, beaucoup d’entre nous sont eux-mêmes des ingénieurs des applications mobile, aussi nous trouvons le potentiel de la trousse à outils de Firebase très intéressant et nous recommandons vivement de le considérer comme un moyen d’accélérer le travail sur les nouveaux projets.

Il y a bien évidemment un revers à tout ça: ces nouveaux outils sont en concurrence dans les verticales du service qui ont déjà connu plus de quatre ans d’innovation et d’amélioration du produit. Nous pensons que Google a vu trop grand en essayant d’en lancer presque une douzaine simultanément. Il en a découlé que beaucoup de ces nouveaux composants partent dans tous les sens. Il peut être difficile de savoir quand votre évolution a atteint le point où elle nécessite quelque chose de plus puissant et les lacunes peuvent ne pas être visibles avant qu’il ne soit trop tard et après l’élaboration d’un élément central de votre application en plus de la plate-forme.

Branch, résoudre le problème de la divulgation de l’application par une meilleure liaison a été au centre de notre attention au cours de ces trois dernières années, ce qui signifie que nous nous occupons des liaisons ciblées plus que quiconque en ce monde (300 millions par jour en décembre 2016). Dans cette optique, intéressons-nous de plus près au module de liaisons universelles Firebase et voyons comment il se positionne par rapport à la plate-forme de liaison Branch. Nous aborderons également la facilité de la mise en œuvre de Branch par rapport aux liaisons dynamiques, si vous avez besoin de plus de puissance, tout en continuant à utiliser le reste de la trousse à outils de Firebase.

Liaisons dynamiques Firebase

Dans le blog de présentation des liaisons dynamiques écrit par l’équipe de Firebase, le problème central qu’ils tentent de résoudre est mis en évidence: la difficulté d’établir une liaison avec un contenu à l’intérieur des applications. Au fil de l’article, certaines exigences clés s’appliquant à tous les systèmes de liaison des applications mobiles sont définies:

  • Lancer l’application lorsque celle-ci est installée et diriger l’utilisateur directement vers le contenu
  • Si elle n’est pas installée, dirigez les utilisateurs vers App/Play Store puis vers le contenu après le téléchargement
  • Récupérer les données sur l’analyse et le suivi

Les liaisons dynamiques assument ces exigences de base. Du moins, un nombre d’entre elles suffisamment important pour vous donner un aperçu du potentiel de la liaison ciblée. Cependant, il s’agit du composant de Firebase le plus récent et le moins développé et très rapidement, vous vous trouverez à court de possibilités lorsque vous voudrez faire quelque chose de plus évolué.

Liaisons dynamiques != Liaisons hébergées par Branch

Les critères énoncés ci-dessus sont identiques à ceux identifiés lors du démarrage de la création de Branch en 2014. Ils sont le noyau central d’un service de liaison ciblée réussie et la base de tout ce que Branch a créé, dans la mesure où nous sommes devenus l’infrastructure de gestion de la liaison des meilleures applications du monde. Mais les difficultés surgissent dans les menus détails. En tant que développeur d’applications, que pouvez-vous réellement faire avec ces liaisons?

Liaisons dynamiques Branch
Génération des liaisons au cœur de l’application X X
Génération de liaisons en utilisant uniquement le tableau de bord en ligne X X
URL de liaison sans spam X
Paramètres de données modulables et personnalisés par liaison   X* X
Routage vers le contenu spécifique, même lorsque l’application n’est pas installée X X
Réponse normalisée des données de la liaison sous le format JSON   X
Attribution de la première installation   X
Garantie de la précision d’adéquation lors de la première installation   X
Identification des utilisateurs uniques (pour les renvois, etc.)   X
Assistance technique de pointe et soutenue par les niveaux de service SLA X
Gestion complète des cas limites (y compris Facebook et le courrier électronique) X


* Doit être codé manuellement dans le cadre de l’URL de la liaison

Un exemple pratique

Sous forme de tableau, tout semble parfait, mais que se passe-t-il si nous voulons mettre en œuvre une fonctionnalité équivalente de liaison ciblée dans une application simple sous iOS, comme notre application bureautique Branch Room Maps app? Comparons exactement les codes.

Nous devons d’abord ouvrir une session et gérer les liaisons entrantes. Voici ce que nous obtenons en utilisant Firebase:

import UIKit
import Firebase
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let customURLScheme = branchmaps // Hmmm…why?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Set up the SDK
FIROptions.default().deepLinkURLScheme = self.customURLScheme
FIRApp.configure()
return true
}
// This extra call to the open url method often causes confusion…but both are necessary!
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool {
return application(app, open: url, sourceApplication: nil, annotation: [:])
}
// Here, we handle URI scheme links, and (more importantly) the initial launch after a new install
// This can also cause confusion, because the initial launch is not a URI link and yet is still handled here
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
let dynamicLink = FIRDynamicLinks.dynamicLinks()?.dynamicLink(fromCustomSchemeURL: url)
if let dynamicLink = dynamicLink {
// We can see the URL of the link…
dump(dynamicLink.url)
// …and then pull it apart to use the pieces
let deepLink = URLComponents(url: dynamicLink.url!, resolvingAgainstBaseURL: false)!
let deepLinkQueryString = deepLink.queryItems
// Filtering through the results to see if they contain the parameter we want
if let roomID = deepLinkQueryString!.filter({$0.name == roomID}).first?.value {
// Set up the transition
let destination = self.window?.rootViewController?.storyboard?.instantiateViewController(withIdentifier: roomDetails) as! ViewController
destination.roomToShow = String(describing: roomID)
self.window?.rootViewController?.present(destination, animated: true, completion: nil)
}
return true
}
return false
}
// Aaaaand now do it all again for Universal Links
@available(iOS 8.0, *)
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
guard let dynamicLinks = FIRDynamicLinks.dynamicLinks() else {
return false
}
let handled = dynamicLinks.handleUniversalLink(userActivity.webpageURL!) { (dynamicLink, error) in
dump(dynamicLink!.url)
let deepLink = URLComponents(url: dynamicLink!.url!, resolvingAgainstBaseURL: false)!
let deepLinkQueryString = deepLink.queryItems
if let roomID = deepLinkQueryString!.filter({$0.name == roomID}).first?.value {
let destination = self.window?.rootViewController?.storyboard?.instantiateViewController(withIdentifier: roomDetails) as! ViewController
destination.roomToShow = String(describing: roomID)
self.window?.rootViewController?.present(destination, animated: true, completion: nil)
}
}
return handled
}
}

 

Et voici la même chose, avec la mise en œuvre en utilisant Branch:

import UIKit
import Branch
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Set up the SDK
let branch: Branch = Branch.getInstance()
// Get a bunch of extra logging output
branch.setDebug()
// No need to manually configure any transitions, because the Branch SDK can do that automatically
// Of course, you can do it manually too if you need more flexibility
let controller = UIStoryboard.init(name: Main, bundle: Bundle.main).instantiateViewController(withIdentifier: roomDetails)
branch.registerDeepLinkController(controller, forKey: room_name)
// Start the session and get all the link data. This occurs on every launch, even if a link was not opened
// This is also where the link data from a new install is captured
branch.initSession(launchOptions: launchOptions, automaticallyDisplayDeepLinkController: true) { (params, error) in
if (error == nil) {
// We can look at the contents of the link, and a bunch of other interesting things
dump(params)
}
}
return true
}
// Here, we check for URI scheme links
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
// If we find one, pass it back to the deep link handler for unpacking
Branch.getInstance().handleDeepLink(url);
return true
}
// Also check for Universal Links
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
// If we find one, it goes back to the deep link handler for unpacking too
return Branch.getInstance().continue(userActivity)
}
}

 

Comme vous pouvez le constater, il n’y a pratiquement pas de différences à ce stade. La plupart des choses sont légèrement plus simples avec Branch, mais rien qu’un bon informaticien ne puisse gérer.

Ensuite, créons quelques liaisons. D’abord avec Firebase:

@IBAction func shareButton(_ sender: UIButton) {
if let selectedRoom = (RoomData.allRoomsArray().filter{ $0.roomID == roomToShow }).first {
// We need to specify everything for each link…so let’s start with the base URL on the web
// Also need to manually append any custom data params we want passed through
let roomLink = https://branch.io/room?roomID=\(selectedRoom.roomID)
// Next, wrap that URL into the Firebase link and add required control params
let firebaseLink = https://x2z5q.app.goo.gl/?link=\(roomLink.addingPercentEncoding(withAllowedCharacters: .alphanumerics)!)&ibi=io.branch.branchmap
// Configure and display the stock iOS share sheet
let shareSheet = UIActivityViewController(activityItems: [ firebaseLink ], applicationActivities: nil)
shareSheet.popoverPresentationController?.sourceView = self.view
self.present(_: shareSheet, animated: true, completion: {
print(Generated \(firebaseLink) sharing link for \(selectedRoom.roomID))
})
}
}

 

Maintenant, avec Branch:

@IBAction func shareButton(_ sender: UIButton) {
// Set up some basic info about the link we are going to create
let linkProperties = BranchLinkProperties()
linkProperties.feature = sharing
// Define a container to store link data
let branchUniversalObject = BranchUniversalObject()
if let selectedRoom = (RoomData.allRoomsArray().filter{ $0.roomName == roomToShow }).first {
// Insert all the link data…these are just few of the options
// Many configuration items can be omitted because they are inherited from the main Branch app config
branchUniversalObject.canonicalIdentifier = room/\(selectedRoom.roomID) // This one lets us dedup the same piece of content across many links
branchUniversalObject.title = selectedRoom.roomName
branchUniversalObject.addMetadataKey(room_name, value: selectedRoom.roomName) // We can have as many of these as we want
// Use the pre-packaged share sheet method
branchUniversalObject.showShareSheet(with: linkProperties, andShareText: nil, from: self, completion: { (activity, finished) in
print(Generated sharing link for \(selectedRoom.roomName))
})
}
}

 

Ici encore, un peu plus de travail manuel pour le code avec Firebase, cependant la vraie différence réside dans les URL de liaison elles-mêmes (les liaisons de marque ont une réelle importance).

Mais le plus important est de loin ce que vous pouvez réellement faire avec ces liaisons lors de leur utilisation. Voici les données que vous obtenez à partir de ces relevés d’image mémoire de retour dans AppDelegate:

Firebase:

url: https://branch.io/room?roomID=PineCone

 

Branch:

+click_timestamp: 1482541476
+clicked_branch_link: 1
+is_first_session: 0
+match_guaranteed: 1
+referrer: https://www.google.com/
+phone_number: //only returned when link is SMSed from desktop to mobile
~creation_source: 3
~referring_link: https://branchmaps.app.link/D1PpymBZlz
~feature: sharing
~channel: Pasteboard
~id: 341010052121261919
$one_time_use: 0
$og_title: Pine Cone
$identity_id: 339834809826614244
$canonical_identifier: room/PineCone
$publicly_indexable: 1
$exp_date: 0
room_name: Pine Cone

 

Dans ce cas, les deux plates-formes ne se ressemblent en rien. Branch vous propose une liste complète de paramètres contextuels utiles, parmi lesquels la détection de l’installation (+is_first_session) et la précision d’adéquation (+match_guaranteed). La détection de l’installation est cruciale pour la création d’expériences telles que l’intégration personnalisée et la précision d’adéquation permet la liaison ciblée au contenu personnalisé, en vous assurant que vous bénéficiez du bon utilisateur, ce que Branch fait mieux que quiconque dans cet écosystème.

En fait, certains de nos clients ont tellement confiance dans notre précision qu’ils utilisent les liens de Branch pour enregistrer automatiquement les utilisateurs dans une application la première fois qu’ils l’ouvrent.

Firebase renvoie une simple URL brute.

Et c’est là où les liaisons universelles s’arrêtent. Elles enverront vos utilisateurs là où vous le désirez (la plupart du temps c’est-à-dire si vous ne vous heurtez pas à trop de cas limites) et ils effectueront le suivi des clics sur le lien, mais pas grand chose de plus. D’autre part, Branch ne vient que de démarrer. Pour nous, un système de liaison ciblée solide n’est que le cadre dans lequel construire tout le reste:

  • Bannières intelligentes des parcours: la bannière intelligente d’application la plus puissante et flexible disponible sur le marché.
  • Deepviews: augmente la conversion en fournissant aux utilisateurs un aperçu du contenu de votre application avant de la télécharger.
  • E-mails avec liaisons ciblées: ajoute automatiquement des liaisons ciblées à vos e-mails commerciaux.
  • Références: effectue le suivi des références et accorde des crédits à vos utilisateurs.
  • Intégration des données: envoie automatiquement les données d’analyse de votre liaison aux outils externes.
  • Text Me The App: permet aux visiteurs du bureau d’envoyer eux-mêmes un lien de téléchargement par SMS.
  • Analyse complète: assure le suivi des clics sur votre liaison, des installations, du contenu le plus performant, des utilisateurs les plus importants et plus encore.

De plus, comme nous sommes nous-mêmes des développeurs et des programmateurs d’application, nous comprenons combien il est important d’obtenir de l’aide en cas de besoin. Nous examinons chaque question sur StackOverflow avec la balise Branch.io, et nos équipes d’intégration offrent une assistance illimitée gratuite à TOUS les partenaires.

Comment tirer le meilleur parti de ces deux mondes

Voici le meilleur: vous n’avez pas à choisir. Firebase est mis en œuvre sous forme d’une série de kits SDK indépendants et modulables. Comme de toutes façons, vous devez ajouter un autre kit SDK pour mettre en œuvre les liaisons dynamiques, il est tout aussi simple d’utiliser Branch à la place. En fait, c’est probablement plus aisé ! Vous pouvez bénéficier de tous les avantages de la plate-forme AaaS Firebase et la flexibilité et la puissance du système de liaison ciblée le plus perfectionné du monde.

Commencer