Skip to content

Vinculación en profundidad en Content Cards

Aprende a crear vínculos profundos dentro de una Content Card utilizando el SDK de Braze. Para obtener más información sobre los vínculos profundos, consulta ¿Qué es la vinculación en profundidad?.

En este momento, los vínculos profundos de Content Cards no son compatibles con el SDK Web de Braze.

Requisitos previos

Antes de poder utilizar esta característica, tendrás que integrar el SDK de Android Braze.

Creación de un delegado universal

El SDK de Android ofrece la posibilidad de establecer un único objeto delegado para gestionar de forma personalizada todos los vínculos profundos abiertos por Braze a través de Content Cards, mensajes dentro de la aplicación y notificaciones push.

Tu objeto delegado debe implementar la interfaz IBrazeDeeplinkHandler y configurarse mediante BrazeDeeplinkHandler.setBrazeDeeplinkHandler(). En la mayoría de los casos, el delegado debe establecerse en el Application.onCreate() de tu aplicación.

A continuación se muestra un ejemplo de cómo anular el comportamiento predeterminado de UriAction con indicadores de intención personalizados y un comportamiento personalizado para las URL de YouTube:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class CustomDeeplinkHandler implements IBrazeDeeplinkHandler {
  private static final String TAG = BrazeLogger.getBrazeLogTag(CustomDeeplinkHandler.class);

  @Override
  public void gotoUri(Context context, UriAction uriAction) {
    String uri = uriAction.getUri().toString();
    // Open YouTube URLs in the YouTube app and not our app
    if (!StringUtils.isNullOrBlank(uri) && uri.contains("youtube.com")) {
      uriAction.setUseWebView(false);
    }

    CustomUriAction customUriAction = new CustomUriAction(uriAction);
    customUriAction.execute(context);
  }

  public static class CustomUriAction extends UriAction {

    public CustomUriAction(@NonNull UriAction uriAction) {
      super(uriAction);
    }

    @Override
    protected void openUriWithActionView(Context context, Uri uri, Bundle extras) {
      Intent intent = getActionViewIntent(context, uri, extras);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
      if (intent.resolveActivity(context.getPackageManager()) != null) {
        context.startActivity(intent);
      } else {
        BrazeLogger.w(TAG, "Could not find appropriate activity to open for deep link " + uri + ".");
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class CustomDeeplinkHandler : IBrazeDeeplinkHandler {

  override fun gotoUri(context: Context, uriAction: UriAction) {
    val uri = uriAction.uri.toString()
    // Open YouTube URLs in the YouTube app and not our app
    if (!StringUtils.isNullOrBlank(uri) && uri.contains("youtube.com")) {
      uriAction.useWebView = false
    }

    val customUriAction = CustomUriAction(uriAction)
    customUriAction.execute(context)
  }

  class CustomUriAction(uriAction: UriAction) : UriAction(uriAction) {

    override fun openUriWithActionView(context: Context, uri: Uri, extras: Bundle) {
      val intent = getActionViewIntent(context, uri, extras)
      intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
      if (intent.resolveActivity(context.packageManager) != null) {
        context.startActivity(intent)
      } else {
        BrazeLogger.w(TAG, "Could not find appropriate activity to open for deep link $uri.")
      }
    }
  }

  companion object {
    private val TAG = BrazeLogger.getBrazeLogTag(CustomDeeplinkHandler::class.java)
  }
}

Vinculación en profundidad a la configuración de la aplicación

Para permitir que los vínculos profundos abran directamente la configuración de tu aplicación, necesitarás un BrazeDeeplinkHandler personalizado. En el siguiente ejemplo, la presencia de un par clave-valor personalizado llamado open_notification_page hará que el vínculo profundo abra la página de configuración de la aplicación:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
BrazeDeeplinkHandler.setBrazeDeeplinkHandler(new IBrazeDeeplinkHandler() {
  @Override
  public void gotoUri(Context context, UriAction uriAction) {
    final Bundle extras = uriAction.getExtras();
    if (extras.containsKey("open_notification_page")) {
      Intent intent = new Intent();
      intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

      //for Android 5-7
      intent.putExtra("app_package", context.getPackageName());
      intent.putExtra("app_uid", context.getApplicationInfo().uid);

      // for Android 8 and later
      intent.putExtra("android.provider.extra.APP_PACKAGE", context.getPackageName());
      context.startActivity(intent);
    }
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
BrazeDeeplinkHandler.setBrazeDeeplinkHandler(object : IBrazeDeeplinkHandler {
  override fun gotoUri(context: Context, uriAction: UriAction) {
    val extras = uriAction.extras
    if (extras.containsKey("open_notification_page")) {
      val intent = Intent()
      intent.action = "android.settings.APP_NOTIFICATION_SETTINGS"
      intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK

      //for Android 5-7
      intent.putExtra("app_package", context.packageName)
      intent.putExtra("app_uid", context.applicationInfo.uid)

      // for Android 8 and later
      intent.putExtra("android.provider.extra.APP_PACKAGE", context.packageName)
      context.startActivity(intent)
    }
  }
})

Personalización de la actividad WebView

Cuando Braze abre vínculos profundos de sitios web dentro de la aplicación, estos son gestionados por BrazeWebViewActivity.

Para cambiar esto:

  1. Crea una nueva Activity que gestione la URL de destino de Intent.getExtras() con la clave com.braze.Constants.BRAZE_WEBVIEW_URL_EXTRA. Para ver un ejemplo, consulta BrazeWebViewActivity.kt.
  2. Añade esa actividad a AndroidManifest.xml y establece exported en false.
    1
    2
    3
    
     <activity
         android:name=".MyCustomWebViewActivity"
         android:exported="false" />
    
  3. Configura tu Activity personalizada en un objeto constructor de BrazeConfig. Construye el builder y pásalo a Braze.configure() en tu Application.onCreate().
1
2
3
4
5
BrazeConfig brazeConfig = new BrazeConfig.Builder()
    .setCustomWebViewActivityClass(MyCustomWebViewActivity::class)
    ...
    .build();
Braze.configure(this, brazeConfig);
1
2
3
4
5
val brazeConfig = BrazeConfig.Builder()
    .setCustomWebViewActivityClass(MyCustomWebViewActivity::class.java)
    ...
    .build()
Braze.configure(this, brazeConfig)

Solución de problemas

Si los vínculos profundos de las notificaciones push no funcionan en Android, prueba los siguientes pasos:

  1. Prueba el vínculo profundo fuera de Braze. Abre la URL del vínculo profundo desde otra aplicación, como el correo electrónico o un navegador. Si no abre tu aplicación, es posible que el vínculo profundo no esté configurado correctamente en tu AndroidManifest.xml. Para más información, consulta la documentación de Android sobre Crear vínculos profundos.
  2. Comprueba que la gestión automática de vínculos profundos esté habilitada. Verifica que com_braze_handle_push_deep_links_automatically esté establecido en true en braze.xml, o configura esta opción mediante la configuración en tiempo de ejecución. Sin esta configuración, Braze no abre automáticamente tu aplicación ni el destino del vínculo profundo cuando alguien toca una notificación push.
  3. Verifica tu delegado de gestión de vínculos profundos. Si configuraste un IBrazeDeeplinkHandler personalizado, confirma que tu implementación de gotoUri gestiona la URI y no la descarta.
  4. Prueba en distintos canales. Si el mismo vínculo profundo funciona en un mensaje dentro de la aplicación pero no desde push, es probable que el problema esté en la gestión de vínculos profundos de push, no en el vínculo profundo en sí.

Uso de Jetpack Compose

Para gestionar vínculos profundos cuando usas Jetpack Compose con NavHost:

  1. Asegúrate de que la actividad que gestiona tu vínculo profundo esté registrada en el manifiesto de Android.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
     <activity
       ...
       <intent-filter>
         <action android:name="android.intent.action.VIEW" />
         <category android:name="android.intent.category.BROWSABLE" />
         <category android:name="android.intent.category.DEFAULT" />
         <data
             android:host="articles"
             android:scheme="myapp" />
       </intent-filter>
     </activity>
    
  2. En NavHost, especifica qué vínculos profundos quieres que gestione.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
     composableWithCompositionLocal(
         route = "YOUR_ROUTE_HERE",
         deepLinks = listOf(navDeepLink {
             uriPattern = "myapp://articles/{${MainDestinations.ARTICLE_ID_KEY}}"
         }),
         arguments = listOf(
             navArgument(MainDestinations.ARTICLE_ID_KEY) {
                 type = NavType.LongType
             }
         ),
     ) { backStackEntry ->
         val arguments = requireNotNull(backStackEntry.arguments)
         val articleId = arguments.getLong(MainDestinations.ARTICLE_ID_KEY)
         ArticleDetail(
             articleId
         )
     }
    
  3. Dependiendo de la arquitectura de tu aplicación, es posible que también necesites gestionar la nueva intención que se envía a tu actividad actual.
    1
    2
    3
    4
    5
    6
    7
    
     DisposableEffect(Unit) {
         val listener = Consumer<Intent> {
             navHostController.handleDeepLink(it)
         }
         addOnNewIntentListener(listener)
         onDispose { removeOnNewIntentListener(listener) }
     }
    

Requisitos previos

Antes de poder utilizar esta característica, tendrás que integrar el SDK de Swift Braze.

Manejo de vínculos profundos

Paso 1: Registrar un plan

Para gestionar la vinculación en profundidad, debe indicarse un esquema personalizado en tu archivo Info.plist. La estructura de navegación está definida por una matriz de diccionarios. Cada uno de esos diccionarios contiene una matriz de cadenas.

Utiliza Xcode para editar tu archivo Info.plist:

  1. Añade una nueva clave, URL types. Xcode lo convertirá automáticamente en una matriz que contiene un diccionario llamado Item 0.
  2. Dentro de Item 0, añade una clave URL identifier. Ajusta el valor a tu esquema personalizado.
  3. Dentro de Item 0, añade una clave URL Schemes. Será automáticamente una matriz que contendrá una cadena Item 0.
  4. Configura URL Schemes » Item 0 a tu esquema personalizado.

Alternativamente, si deseas editar tu archivo Info.plist directamente, puedes seguir esta especificación:

1
2
3
4
5
6
7
8
9
10
11
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLName</key>
        <string>YOUR.SCHEME</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>YOUR.SCHEME</string>
        </array>
    </dict>
</array>

Paso 2: Añadir una lista de permitidos para el esquema

Debes declarar los esquemas de URL que deseas pasar a canOpenURL(_:) añadiendo la clave LSApplicationQueriesSchemes al archivo Info.plist de tu aplicación. Intentar llamar a esquemas fuera de esta lista permitida hará que el sistema registre un error en los registros del dispositivo, y el vínculo profundo no se abrirá. Un ejemplo de este error tendrá el siguiente aspecto:

1
<Warning>: -canOpenURL: failed for URL: "yourapp://deeplink" – error: "This app is not allowed to query for scheme yourapp"

Por ejemplo, si un mensaje dentro de la aplicación debe abrir la aplicación de Facebook al tocarlo, la aplicación tiene que tener el esquema personalizado de Facebook (fb) en tu lista de permitidos. De lo contrario, el sistema rechazará el deep link. Los vínculos profundos que dirigen a una página o vista dentro de tu propia aplicación siguen requiriendo que el esquema personalizado de tu aplicación aparezca en el sitio Info.plist de tu aplicación.

Tu lista de permitidos de ejemplo podría ser algo así

1
2
3
4
5
6
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>myapp</string>
    <string>fb</string>
    <string>twitter</string>
</array>

Para más información, consulta la documentación de Apple sobre la tecla LSApplicationQueriesSchemes.

Paso 3: Implementa un controlador

Tras activar tu aplicación, iOS llamará al método application:openURL:options:. El argumento importante es el objeto NSURL.

1
2
3
4
5
6
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
  let path = url.path
  let query = url.query
  // Insert your code here to take some action based upon the path and query.
  return true
}
1
2
3
4
5
6
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
  NSString *path  = [url path];
  NSString *query = [url query];
  // Insert your code here to take some action based upon the path and query.
  return YES;
}

Seguridad de transporte de aplicaciones (ATS)

Según la definición de Apple, «App Transport Security es una característica que mejora la seguridad de las conexiones entre una aplicación y los servicios Web». La característica consiste en requisitos de conexión predeterminados que se ajustan a las mejores prácticas para conexiones seguras. Las aplicaciones pueden anular este comportamiento predeterminado y desactivar la seguridad del transporte”.

El ATS se aplica por predeterminado. Requiere que todas las conexiones utilicen HTTPS y estén encriptadas mediante TLS 1.2 con confidencialidad directa. Consulta los Requisitos para conectarse mediante ATS para obtener más información. Todas las imágenes servidas por Braze a dispositivos finales son gestionadas por una red de entrega de contenidos (“CDN”) que admite TLS 1.2 y es compatible con ATS.

A menos que se especifiquen como excepciones en la aplicaciónInfo.plist, las conexiones que no cumplan estos requisitos fallarán con errores similares a los siguientes.

Ejemplo de error 1:

1
2
CFNetwork SSLHandshake failed (-9801)
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred, and a secure connection to the server cannot be made."

Ejemplo de error 2:

1
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

El cumplimiento de la ATS se aplica a los enlaces abiertos dentro de la aplicación móvil (nuestro tratamiento predeterminado de los enlaces en los que se hace clic) y no se aplica a los sitios abiertos externamente a través de un navegador web.

Trabajar con ATS

Puedes gestionar los ATS de cualquiera de las siguientes maneras, pero te recomendamos que cumplas con los requisitos de los ATS.

Tu integración con Braze puede satisfacer los requisitos de ATS asegurándote de que cualquier enlace existente al que dirijas a los usuarios (por ejemplo, mediante campañas de mensajería dentro de la aplicación y notificaciones push) satisfaga los requisitos de ATS. Aunque hay formas de eludir las restricciones de la ATS, nuestra recomendación es que te asegures de que todas las URL enlazadas cumplen la ATS. Dado el creciente énfasis de Apple en la seguridad de las aplicaciones, no está garantizado que Apple admita los siguientes enfoques para permitir excepciones ATS.

Puedes permitir que un subconjunto de enlaces con determinados dominios o esquemas sean tratados como excepciones a las normas ATS. Tu integración Braze satisfará los requisitos de ATS si cada enlace que utilices en un canal de mensajería Braze es compatible con ATS o se gestiona mediante una excepción.

Para añadir un dominio como excepción del ATS, añade lo siguiente al archivo Info.plist de tu aplicación:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>example.com</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
</dict>

Consulta el artículo de Apple sobre las claves de seguridad para el transporte de aplicaciones para obtener más información.

Puedes desactivar ATS por completo. Ten en cuenta que no es una práctica recomendada, tanto por la pérdida de protecciones de seguridad como por la futura compatibilidad con iOS. Para desactivar ATS, inserta lo siguiente en el archivo Info.plist de tu aplicación:

1
2
3
4
5
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

Descodificación de URL

El SDK codifica porcentualmente los enlaces para crear URL válidos. Todos los caracteres de enlace que no estén permitidos en una URL correctamente formada, como los caracteres Unicode, se escaparán en porcentaje.

Para descodificar un enlace codificado, utiliza la propiedad String removingPercentEncoding. También debes devolver true en la dirección BrazeDelegate.braze(_:shouldOpenURL:). Se necesita una llamada a la acción para desencadenar el manejo de la URL por parte de tu aplicación. Por ejemplo:

1
2
3
4
5
  func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    let urlString = url.absoluteString.removingPercentEncoding
    // Handle urlString
    return true
  }
1
2
3
4
5
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<NSString *, id> *)options {
  NSString *urlString = [url.absoluteString stringByRemovingPercentEncoding];
  // Handle urlString
  return YES;
}

Vinculación en profundidad con la configuración de la aplicación

Puedes aprovecharUIApplicationOpenSettingsURLString para dirigir a los usuarios a la configuración de tu aplicación desde las notificaciones push y los mensajes dentro de la aplicación de Braze.

Para llevar a los usuarios de tu aplicación a la configuración de iOS:

  1. En primer lugar, asegúrate de que tu aplicación está configurada para enlaces profundos basados en esquemas o enlaces universales.
  2. Decide un URI para la vinculación en profundidad a la página de configuración (por ejemplo, myapp://settings o https://www.braze.com/settings).
  3. Si utilizas vínculos profundos personalizados basados en esquemas, añade el siguiente código a tu método application:openURL:options::
1
2
3
4
5
6
7
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
  let path = url.path
  if (path == "settings") {
    UIApplication.shared.openURL(URL(string:UIApplication.openSettingsURLString)!)
  }
  return true
}
1
2
3
4
5
6
7
8
9
10
- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
  NSString *path  = [url path];
  if ([path isEqualToString:@"settings"]) {
    NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
    [[UIApplication sharedApplication] openURL:settingsURL];
  }
  return YES;
}

Opciones de personalización

Personalización predeterminada de WebView

La clase Braze.WebViewController muestra las URL web abiertas por el SDK, normalmente, cuando se selecciona “Abrir URL web dentro de la aplicación” para un vínculo profundo a la web.

Puedes personalizar el Braze.WebViewController mediante el método delegado BrazeDelegate.braze(_:willPresentModalWithContext:).

Personalización de la gestión de enlaces

El protocolo BrazeDelegate puede utilizarse para personalizar el tratamiento de las URL, como los vínculos profundos, las URL web y los vínculos universales. Para configurar el delegado durante la inicialización de Braze, establece un objeto delegado en la instancia de Braze. A continuación, Braze llamará a la implementación de shouldOpenURL de tu delegado antes de gestionar cualquier URI.

Braze admite enlaces universales en notificaciones push, mensajes dentro de la aplicación y tarjetas de contenido. Para habilitar la compatibilidad con el enlace universal, configuration.forwardUniversalLinks debe estar configurado en true.

Cuando esté habilitado, Braze reenviará los enlaces universales a la página AppDelegate de tu aplicación mediante el método application:continueUserActivity:restorationHandler: método.

Tu aplicación también debe estar configurada para gestionar enlaces universales. Consulta la documentación de Apple para asegurarte de que tu aplicación está configurada correctamente para los enlaces universales.

Ejemplos

BrazeDelegate

Aquí tienes un ejemplo utilizando BrazeDelegate. Para obtener más información, consulta la referencia de Braze SWIFT SDK.

1
2
3
4
5
6
7
8
func braze(_ braze: Braze, shouldOpenURL context: Braze.URLContext) -> Bool {
  if context.url.host == "MY-DOMAIN.com" {
    // Custom handle link here
    return false
  }
  // Let Braze handle links otherwise
  return true
}
1
2
3
4
5
6
7
8
- (BOOL)braze:(Braze *)braze shouldOpenURL:(BRZURLContext *)context {
  if ([[context.url.host lowercaseString] isEqualToString:@"MY-DOMAIN.com"]) {
    // Custom handle link here
    return NO;
  }
  // Let Braze handle links otherwise
  return YES;
}
New Stuff!