Cordova PhoneGap Ionic

iOS 11.2上通用链接行为不一致

将设备更新到iOS 11.2后,我们发现安装应用后,应用的AASA文件不再可靠地下载到用户的设备上。因此,点击通用链接将不再一致地打开该应用程序。您可以在Branch链接上设置强制uri重定向模式 ,以使用URI方案打开应用。在 Apple Bug报告中查看问题的详细信息

配置 Branch

图像
图像

配置应用

  • Cordova and Ionic
<!-- sample config.xml -->
    <widget id="com.eneff.branch.cordovatestbed" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
      <!-- Branch -->
      <plugin name="branch-cordova-sdk" spec="^4.0.0" />
      <branch-config>
        <branch-key value="key_live_ndqptlgXNE4LHqIahH1WIpbiyFlb62J3" />
        <uri-scheme value="branchcordova" />
        <link-domain value="cordova.app.link" />  <!-- Required app.link domain -->
        <link-domain value="cordova-alternate.app.link" />  <!-- Required alternate.app.link domain -->
        <ios-team-release value="PW4Q8885U7" />
      </branch-config>
  <!-- sample config.xml -->
    <widget id="com.eneff.branch.cordovatestbed" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:gap="http://phonegap.com/ns/1.0">
      <!-- Branch -->
      <plugin name="branch-cordova-sdk" spec="^4.0.0" />
      <branch-config>
        <branch-key value="key_live_ndqptlgXNE4LHqIahH1WIpbiyFlb62J3" />
        <uri-scheme value="branchcordova" />
        <link-domain value="cordova.app.link" />  <!-- Required app.link domain -->
        <link-domain value="cordova-alternate.app.link" />  <!-- Required alternate.app.link domain -->
        <ios-team-release value="PW4Q8885U7" />
      </branch-config>
  • 更改以下值以匹配您的 Branch Dashboard

  • com.eneff.branch.cordovatestbed

  • key_live_ndqptlgXNE4LHqIahH1WIpbiyFlb62J3
  • branchcordova
  • cordova.app.link
  • PW4Q8885U7

初始化 Branch

  • Cordova and PhoneGap
 // sample index.js
    var app = {
      initialize: function() {
        this.bindEvents();
      },
      bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
        document.addEventListener('resume', this.onDeviceResume, false);
      },
      onDeviceReady: function() {
        app.handleBranch();
      },
      onDeviceResume: function() {
        app.handleBranch();
      },
      handleBranch: function() {
        // Branch initialization
        Branch.initSession().then(function(data) {
          if (data['+clicked_branch_link']) {
            // read deep link data on click
            alert('Deep Link Data: ' + JSON.stringify(data));
          }
        });
      }
    };

    app.initialize();
 // sample app.js
    angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])

    .run(function($ionicPlatform) {
      $ionicPlatform.ready(function() {
        if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
          cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
          cordova.plugins.Keyboard.disableScroll(true);
        }
        if (window.StatusBar) {
          StatusBar.styleDefault();
        }

        // Branch
        $ionicPlatform.on('deviceready', function() {
          handleBranch();
        });

        $ionicPlatform.on('resume', function() {
          handleBranch();
        });

        function handleBranch() {
          // Branch initialization
          Branch.initSession().then(function(data) {
            if (data['+clicked_branch_link']) {
              // read deep link data on click
              alert('Deep Link Data: ' + JSON.stringify(data));
            }
          });
        }
      });
    })
    // ...
 // sample app.component.js
      import { Component } from '@angular/core';
      import { Platform } from 'ionic-angular';
      import { StatusBar, Splashscreen } from 'ionic-native';

      import { TabsPage } from '../tabs/tabs

      @Component({
        template: `<ion-nav [root]="rootPage"></ion-nav>`
      })
      export class MyApp {
        rootPage = TabsPage;

        constructor(platform: Platform) {
          platform.ready().then(() => {
            StatusBar.styleDefault();
            Splashscreen.hide();
            handleBranch();
          });

          platform.resume.subscribe(() => {
            handleBranch();
          });

          // Branch initialization
          const handleBranch = () => {
            // only on devices
            if (!platform.is('cordova')) { return }
            const Branch = window['Branch'];
            Branch.initSession().then(data => {
              if (data['+clicked_branch_link']) {
                // read deep link data on click
                alert('Deep Link Data: ' + JSON.stringify(data));
              }
            });
          }
        }
      }

测试深度链接iOS

  • Branch 控制面板中创建深度链接

  • 从设备中删除您的应用程序

  • 编译您的应用cordova run ios phonegap run ios ionic run ios

  • 粘贴深度链接到 Apple Notes

  • 长按深度链接接 (不是3D Touch)

  • 点击Open in "APP_NAME" 打开您的应用程序示例

测试深度链接 Android

  • Branch 控制面板中创建深度链接

  • 从设备中删除您的应用程序

  • 编译您的应用cordova run android phonegap run android ionic run android

  • 粘贴深度链接到 Google Hangouts

  • 点击深度链接打开您的应用

实现功能

初始化Branch功能

  • 将Branch加载到您的应用中

  • 必须在devicereadyresume上调用

// for development and debugging only
    Branch.setDebug(true)

    // for GDPR compliance (can be called at anytime)
    Branch.disableTracking(true);

    // Branch initialization
    Branch.initSession().then(function(data) {
      if (data['+clicked_branch_link']) {
        // read deep link data on click
        alert('Deep Link Data: ' + JSON.stringify(data))
      }
    })

创建内容引用

  • 使用 Branch Universal Object 封装您要共享的内容(内容或用户)

  • 使用通用对象属性

 // only canonicalIdentifier is required
    var properties = {
      canonicalIdentifier: 'content/123',
      canonicalUrl: 'https://example.com/content/123',
      title: 'Content 123 Title',
      contentDescription: 'Content 123 Description ' + Date.now(),
      contentImageUrl: 'http://lorempixel.com/400/400/',
      price: 12.12,
      currency: 'GBD',
      contentIndexingMode: 'private',
      contentMetadata: {
        custom: 'data',
        testing: 123,
        this_is: true
      }
    }

    // create a branchUniversalObj variable to reference with other Branch methods
    var branchUniversalObj = null
    Branch.createBranchUniversalObject(properties).then(function (res) {
      branchUniversalObj = res
      alert('Response: ' + JSON.stringify(res))
    }).catch(function (err) {
      alert('Error: ' + JSON.stringify(err))
    })

创建深度链接

// optional fields
    var analytics = {
      channel: 'facebook',
      feature: 'onboarding',
      campaign: 'content 123 launch',
      stage: 'new user',
      tags: ['one', 'two', 'three']
    }

    // optional fields
    var properties = {
      $desktop_url: 'http://www.example.com/desktop',
      $android_url: 'http://www.example.com/android',
      $ios_url: 'http://www.example.com/ios',
      $ipad_url: 'http://www.example.com/ipad',
      $match_duration: 2000,
      custom_string: 'data',
      custom_integer: Date.now(),
      custom_boolean: true
    }

    branchUniversalObj.generateShortUrl(analytics, properties).then(function (res) {
      alert('Response: ' + JSON.stringify(res.url))
    }).catch(function (err) {
      alert('Error: ' + JSON.stringify(err))
    })

分享深度链接

 // optional fields
    var analytics = {
      channel: 'facebook',
      feature: 'onboarding',
      campaign: 'content 123 launch',
      stage: 'new user',
      tags: ['one', 'two', 'three']
    }

    // optional fields
    var properties = {
      $desktop_url: 'http://www.example.com/desktop',
      custom_string: 'data',
      custom_integer: Date.now(),
      custom_boolean: true
    }

    var message = 'Check out this link'

    // optional listeners (must be called before showShareSheet)
    branchUniversalObj.onShareSheetLaunched(function (res) {
      // android only
      console.log(res)
    })
    branchUniversalObj.onShareSheetDismissed(function (res) {
      console.log(res)
    })
    branchUniversalObj.onLinkShareResponse(function (res) {
      console.log(res)
    })
    branchUniversalObj.onChannelSelected(function (res) {
      // android only
      console.log(res)
    })

    // share sheet
    branchUniversalObj.showShareSheet(analytics, properties, message)

读取深度链接

  • 从深度链接中提取 Branch 数据

  • 最佳做法是从listener 接收数据(以防止出现race condition)

  • 返回深度链接属性

  • 监听器

// Branch initialization within your deviceready and resume
    Branch.initSession().then(function success(res) {
      if (res["+clicked_branch_link"]) {
        alert("Open app with a Branch deep link: " + JSON.stringify(res));
        // Branch quick link: https://cordova.app.link/uJcOH1IFpM
        // Branch web link: https://cordova-alternate.app.link/uJcOH1IFpM
        // Branch dynamic link: https://cordova.app.link?tags=one&tags=two&tags=three&channel=Copy&feature=onboarding&stage=new+user&campaign=content+123+launch&type=0&duration=0&source=android&data
        // Branch uri scheme: branchcordova://open?link_click_id=link-500015444967786346
        // Branch android intent: intent://open?link_click_id=518106399270344237#Intent;scheme=looprocks;package=com.eneff.branch.cordovatestbed;S.browser_fallback_url=https%3A%2F%2Fcordova.app.link%2FuJcOH1IFpM%3F__branch_flow_type%3Dchrome_deepview%26__branch_flow_id%3D518106399312287278;S.market_referrer=link_click_id-518106399270344237%26utm_source%3DCopy%26utm_campaign%3Dcontent%20123%20launch%26utm_feature%3Donboarding;S.branch_data=%7B%22~feature%22%3A%22onboarding%22%2C%22this_is%22%3A%22true%22%2C%22custom_string%22%3A%22data%22%2C%22testing%22%3A%22123%22%2C%22%24publicly_indexable%22%3A%22false%22%2C%22%24desktop_url%22%3A%22http%3A%2F%2Fwww.example.com%2Fdesktop%22%2C%22%24one_time_use%22%3Afalse%2C%22custom_object%22%3A%22%7B%5C%5C%5C%22random%5C%5C%5C%22%3A%5C%5C%5C%22dictionary%5C%5C%5C%22%7D%22%2C%22~id%22%3A%22517795540654792902%22%2C%22~campaign%22%3A%22content%20123%20launch%22%2C%22%2Bclick_timestamp%22%3A1524764418%2C%22%2Burl%22%3A%22https%3A%2F%2Fcordova.app.link%2FuJcOH1IFpM%22%2C%22custom_boolean%22%3A%22true%22%2C%22custom%22%3A%22data%22%2C%22source%22%3A%22android%22%2C%22%24og_image_url%22%3A%22http%3A%2F%2Florempixel.com%2F400%2F400%2F%22%2C%22%2Bdomain%22%3A%22cordova.app.link%22%2C%22custom_integer%22%3A%221524690301794%22%2C%22~tags%22%3A%5B%22one%22%2C%22two%22%2C%22three%22%5D%2C%22custom_array%22%3A%22%5B1%2C2%2C3%2C4%2C5%5D%22%2C%22~channel%22%3A%22Copy%22%2C%22~creation_source%22%3A2%2C%22%24canonical_identifier%22%3A%22content%2F123%22%2C%22%24og_title%22%3A%22Content%20123%20Title%22%2C%22%24og_description%22%3A%22Content%20123%20Description%201524690296449%22%2C%22%24identity_id%22%3A%22453670943617990547%22%2C%22~stage%22%3A%22new%20user%22%2C%22%2Bclicked_branch_link%22%3Atrue%2C%22%2Bmatch_guaranteed%22%3Atrue%2C%22%2Bis_first_session%22%3Afalse%7D;B.branch_intent=true;end
        // Branch android app link (device controlled): https://cordova.app.link/uJcOH1IFpM
        // Branch ios universal link (device controlled): https://cordova.app.link/uJcOH1IFpM
      } else if (res["+non_branch_link"]) {
        alert("Open app with a non Branch deep link: " + JSON.stringify(res));
        // Competitor uri scheme: anotherurischeme://hello=world
      } else {
        alert("Open app organically");
        // Clicking on app icon or push notification
      }
    })
    .catch(function error(err) {
      logger(err, true);
    });
  • 最新数据
Branch.getLatestReferringParams().then(function(res) {
  alert('Response: ' + JSON.stringify(res))
}).catch(function(err) {
  alert('Error: ' + JSON.stringify(err))
})
  • 初次数据
Branch.getFirstReferringParams().then(function(res) {
  alert('Response: ' + JSON.stringify(res))
}).catch(function(err) {
  alert('Error: ' + JSON.stringify(err))
})

导航至内容

  • 在此方法中处理 Branch.initSession()

  • Branch允许您将任何自定义键值从URL传递到您的应用程序。使用此数据导航到内容,显示个性化的欢迎屏幕,登录用户,提供促销等。

Branch.initSession().then(function(data) {
      if (data['+clicked_branch_link']) {
        // option 1: save to model to be used later
        window.localStorage['branchData'] = data;

        // option 2: navigate to page
        window.location.href = '#/content/123'

        // option 3: display data
        alert(JSON.stringify(data));
      }
    });

展示内容

branchUniversalObj.listOnSpotlight().then(function (res) {
  alert('Response: ' + JSON.stringify(res))
}).catch(function (err) {
  alert('Error: ' + JSON.stringify(err))
})

跟踪内容

branchUniversalObj.registerView().then(function (res) {
  alert('Response: ' + JSON.stringify(res))
}).catch(function (err) {
  alert('Error: ' + JSON.stringify(err))
})

跟踪用户

  • 设置事件、深度链接和推荐的用户标识(电子邮件、ID 和 UUID 等)

  • 使用 Branch 控制面板进行验证

  var userId = '123456'
    Branch.setIdentity(userId).then(function (res) {
      alert('Response: ' + JSON.stringify(res))
    }).catch(function (err) {
      alert('Error: ' + JSON.stringify(err.message))
    })
  • 删除用户身份
Branch.logout().then(function (res) {
      alert('Response: ' + JSON.stringify(res))
    }).catch(function (err) {
      alert('Error: ' + JSON.stringify(err.message))
    })

跟踪事件

  • 注册自定义事件

  • 这些事件命名opencloseinstall ,和referred session 都是Branch预留的

  • 最佳方式之前跟踪用户跟踪事件以将自定义事件与用户相关联

  • 使用 Branch 控制面板进行验证

var eventName = 'clicked_on_this';
var metadata = { 'custom_dictionary': 123, 'anything': 'everything' };
Branch.sendBranchEvent(eventName, metadata);

var eventName = 'clicked_on_this';
Branch.sendBranchEvent(eventName);

追踪商业事件

Branch.getStandardEvents().then(function success(res) {
  var event = res.STANDARD_EVENT_ADD_TO_CART;
  var metadata = {
    customerEventAlias: 'alias name for event',
    transactionID: '1234455',
    currency: 'USD',
    revenue: 1.5,
    shipping: 10.2,
    tax: 12.3,
    coupon: 'test_coupon',
    affiliation: 'test_affiliation',
    description: 'Test add to cart event',
    searchQuery: 'test keyword',
    customData: {
      "Custom_Event_Property_Key1": "Custom_Event_Property_val1",
      "Custom_Event_Property_Key2": "Custom_Event_Property_val2"
    }
  };
  Branch.sendBranchEvent(event, metadata);
}).catch(function error(err) {
  alert("Get Standard Event " + err);
});

处理推荐(referral)

var amount = 10;
var bucket = "this_bucket";
Branch.redeemRewards(amount, bucket).then(function success(res) {
  alert("Response: " + JSON.stringify(res));
}).catch(function error(err) {
  alert("Error: " + JSON.stringify(err));
});

var amount = 10;
Branch.redeemRewards(amount).then(function success(res) {
  alert("Response: " + JSON.stringify(res));
}).catch(function error(err) {
  alert("Error: " + JSON.stringify(err));
});
  • 载入积分
var bucket = "this_bucket";
Branch.loadRewards(bucket).then(function success(res) {
  alert("Response: " + JSON.stringify(res));
}).catch(function error(err) {
  alert("Error: " + JSON.stringify(err));
});

Branch.loadRewards().then(function success(res) {
  alert("Response: " + JSON.stringify(res));
}).catch(function error(err) {
  alert("Error: " + JSON.stringify(err));
});
  • 载入记录
Branch.creditHistory().then(function success(res) {
  alert("Response: " + JSON.stringify(res));
}).catch(function error(err) {
  alert("Error: " + JSON.stringify(err));
});

解决问题

测试:重点

  • 发布您的应用时需要选择"app uses IDFA or GAID"

  • 最好启用 Deepviews 测试:支持的平台

  • 移动浏览器功能: Android 4.4.4+Safari 8+Chrome 32+Firefox 29+

测试:可选的App Config

  • 自定义链接域的附加配置,模拟安装,唯一的bundle id等
<!-- sample config.xml -->
    <widget id="com.eneff.branch.cordovatestbed" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
      <!-- Branch -->
      <plugin name="branch-cordova-sdk" spec="^4.0.0" /> <!-- optional spec -->
      <branch-config>
        <branch-key value="key_live_ndqptlgXNE4LHqIahH1WIpbiyFlb62J3" />
        <uri-scheme value="branchcordova" />
        <link-domain value="yourcustomdomain.com" />
        <link-domain value="cordova.app.link" />  <!-- optional previous link domain -->
        <link-domain value="bnc.lt" />  <!-- optional previous link domain -->
        <ios-team-release value="PW4Q8885U7" /> <!-- required if iOS app -->
        <ios-team-debug value="FG35JLLMXX" /> <!-- optional -->
        <android-prefix value="/WSuf" /> <!-- optional (for bnc.lt) -->
        <android-testmode value="true" /> <!-- optional (simulate installs) -->
      </branch-config>
      
      
 <widget ios-CFBundleIdentifier="com.eneff.branch.cordovatestbedios" android-packageName="com.eneff.branch.cordovatestbedandroid" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">

测试:分支分析

  • 每当用户clicks 在深层链接上并打开应用程序时,将触发installopen

  • installs 代表Branch首次识别app_id和device_id

  • installs 代表新的应用程序用户以及您的Branch深度链接接的成功率

  • installs 不是代表App Store下载

  • non-Branch installs 是安装在Branch深度链接接点击之外的

  • opens 是非安装

  • 如果用户卸载并重新安装该应用程序,则该数字将为open 因为Branch会识别该设备

  • 如果用户拥有该应用程序并点击“Branch”深度链接接,则该位置将为open 因为该用户不是新用户

测试:模拟安装

  • 删除您的应用

  • [iOS] iPhone装置- > 设置 - > 隐私 - > 广告 - > 复位广告标识符 - > 复位标识符

  • [Android] <android-testmode value="true" /> 加到config.xml测试:可选App Config

  • Branch.initSession(); 之前添加Branch.setDebug(true);在初始化Branch之前

  • 点击深度链接接导航到您的$fallback_url ,因为您的应用尚未安装

  • 安装您的应用

  • 打开你的应用

  • Branch.initSession().then(data) 读为+is_first_session = true

测试:支持的平台

  • 支持分支深层链接的应用
iOS 细节 安卓 细节
Facebook NewsFeed 启用 DeepViews 时有效
Facebook Messanger 启用 DeepViews 时有效
Twitter
Pinterest 启用 DeepViews 时有效
Slack
Chrome address bar 🅾 🅾
Chrome web page
FireFox address bar 🅾 🅾
FireFox web page
Safari address bar 🅾
Safari web page
WeChat 启用 DeepViews 时有效
WhatsApp app.link 要求可点击https / http app.link 要求可点击https / http
Hangouts
iMessage
Apple Mail
Gmail

链接数据:通用对象属性

Key 默认 用途 链接属性
canonicalIdentifier (必需) 这是内容的唯一标识符,将帮助Branch在同一事物的许多实例之间进行重复数据删除。合适的选项:具有路径的网站或具有实体标识符的数据库 $canonical_identifier
canonicalUrl 规范网址,用于SEO $canonical_url
title 内容的名称 $og_title
contentDescription 内容说明 $og_description
contentImageUrl 内容的图片网址。必须是绝对路径 $og_image_url
price 商品价格 $amount
currency 表示价格的货币,采用ISO 4217货币代码 $currency
contentIndexingMode "public" 可以设置为"public""private" 。公开表示您希望其他应用发现此内容。 $publicly_indexable
contentMetadata 任何自定义键值数据,例如 { "custom": "data" }

链接数据:深度链接属性

Key 默认 用途
channel 使用频道标记链接到达用户的路线。例如,标记带有"Facebook""LinkedIn" 链接可帮助分别跟踪点击和通过这些路径的安装
feature 这是链接可能与您的应用程序相关的功能。例如,如果您构建了引荐程序,则可以使用“引荐”功能标记链接
campaign 使用此字段可以按实际活动组织链接。例如,如果您启动了一项新功能或产品,并希望围绕该功能或产品进行广告系列
stage 生成链接时,可使用此选项对用户的进度或类别进行分类。例如,如果您具有在1级,3级和5级上可访问的邀请系统,则可以使用此参数来区分在每个级别上生成的链接
tags 这是一个自由格式的条目,具有无限值["string"] 。用它来组织链接数据,其标签不属于上述范围
alias 指定链接别名代替标准编码的短URL,例如yourdomain.com/youralias 。链接别名是无法删除的唯一,不可变的对象。您不能更改现有链接的别名。旧版bnc.lt 域上的别名与通用链接和Spotlight不兼容
type 0 设置为1 可以将生成的链接的深层链接行为限制为一次性使用。将type设置为2 可使链接显示在 Marketing Dashboard 同时将$marketing_title 加到data 。必须是int 。不适用于Cordova SDK(本机SDK的限制)
  • 性质

    • 自订资料
Key 用途
random 123 任何键值对
hello "world" 任何键值对
custom_data true 任何键值对
- Redirection
Key 默认 用途
$fallback_url 更改所有平台的重定向端点-因此您不必按平台启用它。需要注意的是分公司将所有机器人转发到这个URL,其中覆盖任何OG标签中的链接进入。系统范围的默认URL(在“链接设置”中设置)
$desktop_url 更改桌面上的“我的应用程序”页面上的重定向终结点(在“链接设置”中设置)
$ios_url 更改您的应用程序的“ iOS App Store”页面的重定向终结点(在“链接设置”中设置)
$ipad_url 更改iPad $ios_url 的重定向端点
$android_url 更改您应用的Android Play商店页面的重定向端点(在“链接设置”中设置)
$windows_phone_url 更改Windows操作系统Windows Phone默认URL的重定向终结点(在“链接设置”中设置)
$blackberry_url 更改Blackberry OS BlackBerry默认URL的重定向终结点(在“链接设置”中设置)
$fire_url 更改Amazon Fire OS Fire默认URL的重定向终端节点(在“链接设置”中设置)
$ios_wechat_url 更改iOS设备上微信的重定向终结点 $ios_url value
$android_wechat_url 更改Android设备上微信的重定向终结点$android_url
$after_click_url 主点击重定向完成后,URL重定向到
$web_only false 强制打开$fallback_url 而不是应用程序
- Deep Link
Key 默认 用途
$deeplink_path open?link_click_id=1234 为所有平台设置深层链接路径-因此您不必按平台启用它。当Branch SDK收到带有此参数集的链接时,它将自动加载包含在其中的自定义URI路径
$android_deeplink_path 设置Android应用程序的深层链接路径当Branch SDK收到具有此参数集的链接时,它将自动加载包含在其中的自定义URI路径
$ios_deeplink_path 设置iOS应用的深层链接路径。当Branch SDK收到带有此参数集的链接时,它将自动加载包含在其中的自定义URI路径
$match_duration 7200 使您可以控制指纹匹配超时(单击等待应用程序打开匹配的时间),也称为归因窗口。以秒为单位
$always_deeplink true 设置为false 可使链接始终回退到您的移动网站。不适用于通用链接或Android应用链接。
$ios_redirect_timeout 750 控制客户端JS在尝试打开应用程序后重定向到App Store之前等待的超时。以毫秒为单位
$android_redirect_timeout 750 Control the timeout that the clientside JS waits after trying to open up the app before redirecting to the Play Store. Specified in milliseconds
$one_time_use false 设置为true 可以将生成的链接的深层链接行为限制为一次性使用。也可以使用类型设置
$custom_sms_text 发送给SMS链接的文本,供桌面点击此链接。 “设置”中的应用页面必须包含{{ link }} “ Text me me”值
$marketing_title 行销资讯主页深层连结的行销标题
- Content
Key 默认 用途
$publicly_indexable 1 无法在此处修改。需要由“Branch通用对象”设置
$keywords 应该为其寻找内容的关键字。只需使用您要使用的关键字分配一个字符串数组
$canonical_identifier 这是内容的唯一标识符,可帮助Branch在同一事物的许多实例之间进行重复数据删除。合适的选项:具有路径的网站或具有实体标识符的数据库
$exp_date 0 无法在此处修改。需要由“分支通用对象”设置。必须是纪元时间戳,以毫秒为单位
$content_type 这是存在的内容类型的标签。 Apple建议您按照此处所述使用统一类型标识符
- DeepView
Key 默认 用途
$ios_deepview default_template 用于iOS的Deepview模板的名称
$android_deepview default_template 用于Android的Deepview模板的名称
$desktop_deepview default_template 用于桌面的Deepview模板的名称
- Open Graph
Key 默认 用途
$og_title 设置链接的标题,以使其在社交媒体显示中看到
$og_description 设置链接的描述,以便在社交媒体显示中看到
$og_image_url 设置链接的图像,使其在社交媒体显示中看到
$og_image_width 为社交媒体显示设置图像的宽度(以像素为单位)
$og_image_height 为社交媒体显示设置图像的高度(以像素为单位)
$og_video 设置视频,使其在社交媒体显示中看到
$og_url 设置链接的基本URL,因为它将在社交媒体显示中看到
$og_type 设置自定义卡格式链接的类型,因为它将在社交媒体显示中看到
$og_redirect (高级,不建议使用)设置自定义URL,我们将社交媒体机器人重定向到该URL,以便检索所有适当的标签
$og_app_id (很少使用)设置应用程序ID标签
- Twitter
Key 默认 用途
$twitter_card 设置链接的Twitter卡类型
$twitter_title 设置Twitter卡的标题
$twitter_description 设置Twitter卡的描述
$twitter_image_url 设置Twitter卡的图片网址
$twitter_site 设置Twitter网站
$twitter_app_country 设置应用卡的应用国家/地区
$twitter_player 设置视频播放器的URL。默认值为$og_video
$twitter_player_width 设置播放器的宽度(以像素为单位)
$twitter_player_height 设置播放器的高度(以像素为单位)

链接数据:商业属性

类别 类别
0 Animals & Pet Supplies 11 Home & Garden
1 Apparel & Accessories 12 Luggage & Bags
2 Arts & Entertainment 13 Mature
3 Baby & Toddler 14 Media
4 Business & Industrial 15 Office Supplies
5 Camera & Optics 16 Religious & Ceremonial
6 Electronics 17 Software
7 Food, Beverage & Tobacco 18 Sporting Goods
8 Furniture 19 Toys & Games
9 Hardware 20 Vehicles & Parts
10 Health & Beauty
  • 货币
货币 货币 货币
0 AED 60 HKD 120 RSD
1 AFN 61 HNL 121 RUB
2 ALL 62 HRK 122 RWF
3 AMD 63 HTG 123 SAR
4 ANG 64 HUF 124 SBD
5 AOA 65 IDR 125 SCR
6 ARS 66 ILS 126 SDG
7 AUD 67 INR 127 SEK
8 AWG 68 IQD 128 SGD
9 AZN 69 IRR 129 SHP
10 BAM 70 ISK 130 SLL
11 BBD 71 JMD 131 SOS
12 BDT 72 JOD 132 SRD
13 BGN 73 JPY 133 SSP
14 BHD 74 KES 134 STD
15 BIF 75 KGS 135 SYP
16 BMD 76 KHR 136 SZL
17 BND 77 KMF 137 THB
18 BOB 78 KPW 138 TJS
19 BOV 79 KRW 139 TMT
20 BRL 80 KWD 140 TND
21 BSD 81 KYD 141 TOP
22 BTN 82 KZT 142 TRY
23 BWP 83 LAK 143 TTD
24 BYN 84 LBP 144 TWD
25 BYR 85 LKR 145 TZS
26 BZD 86 LRD 146 UAH
27 CAD 87 LSL 147 UGX
28 CDF 88 LYD 148 USD
29 CHE 89 MAD 149 USN
30 CHF 90 MDL 150 UYI
31 CHW 91 MGA 151 UYU
32 CLF 92 MKD 152 UZS
33 CLP 93 MMK 153 VEF
34 CNY 94 MNT 154 VND
35 COP 95 MOP 155 VUV
36 COU 96 MRO 156 WST
37 CRC 97 MUR 157 XAF
38 CUC 98 MVR 158 XAG
39 CUP 99 MWK 159 XAU
40 CVE 100 MXN 160 XBA
41 CZK 101 MXV 161 XBB
42 DJF 102 MYR 162 XBC
43 DKK 103 MZN 163 XBD
44 DOP 104 NAD 164 XCD
45 DZD 105 NGN 165 XDR
46 EGP 106 NIO 166 XFU
47 ERN 107 NOK 167 XOF
48 ETB 108 NPR 168 XPD
49 EUR 109 NZD 169 XPF
50 FJD 110 OMR 170 XPT
51 FKP 111 PAB 171 XSU
52 GBP 112 PEN 172 XTS
53 GEL 113 PGK 173 XUA
54 GHS 114 PHP 174 XXX
55 GIP 115 PKR 175 YER
56 GMD 116 PLN 176 ZAR
57 GNF 117 PYG 177 ZMW
58 GTQ 118 QAR
59 GYD 119 RON

链接数据:Mixpanel集成

  • 如果已安装插件,则与Mixpanel同步
Branch.setRequestMetadata("$mixpanel_distinct_id", "123");

编译:Cordova依赖项

  • Node
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)";
brew update;
brew install node;
  • Xcode

    • 安装 Xcode

    • Open Xcode- >同意SDK许可协议

    • 打开Xcode- >创建新的Xcode项目>运行模拟器>在Mac上同意开发人员模式

  • Android Studio

    • 阅读条指令

    • 安装 JVM

    • 安装 Android Studio

    • 开启Android Studio- > configure -> appearance/system settings/android sdk -> android 6.0 -> Okay

    • 开启Android Studio- > New project -> ... -> Run -> Create new emulator -> Nexus 6p 23 -> Finish

# add to ~/.bash_profile
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$ANDROID_HOME/tools:$PATH
export PATH=$ANDROID_HOME/platform-tools:$PATH


source ~/.bash_profile;


android update sdk;
  • 安装Android SDK构建工具24.0.1

  • 生成Android密钥库

keytool -genkeypair -dname "cn=Full Name, ou=Business Unit, o=Company, c=US" -alias release -keypass aaa111 -keystore release.keystore -storepass aaa111 -validity 10000
keytool -list -v -keystore release.keystore
  • Genymotion [可选]

编译:显示控制台日志

  • iOS模拟器

    • cordova run ios;

    • Safari- > Preferences -> Advance -> Show Develop menu in menu bar

    • Safari- > Develop -> Simulator -> index.html -> Console

    • 可能需要拔出并重新插入设备

    • 可能需要打开Xcode并更新配置文件

  • iOS Xcode

    • cordova plugin add cordova-plugin-console;

    • cordova build ios;

    • Xcode- > APP_LOCATION/platforms/ios/APP_NAME.Xcodeproj

    • Xcode- > App -> General -> Signing -> Team

    • Xcode- > Product -> Run

    • Xcode- > View -> Debug Area -> Activate Console

  • Android设备

    • 插入设备

    • cordova run android;

    • 铬- > [chrome://inspect/#devices](chrome://inspect/#devices) - > Console

  • Android Genymotion

    • Genymotion- > Start

    • cordova run android;

    • 铬- > [chrome://inspect/#devices](chrome://inspect/#devices) - > Console

编译:更新Branch SDK

  • 获得最新的改进和功能
# terminal
cordova plugin remove io.branch.sdk
cordova plugin remove branch-cordova-sdk
<!-- config.xml -->
<plugin name="branch-cordova-sdk" spec="^4.0.0" />

编译:不兼容

  • 以下插件不适用于Branch SDK

  • Branch SDK也不支持PhoneGap Build,因为我们需要插件勾子来启用Entitlements,通用链接,应用程序链接和URI Scheme重定向,但是PhoneGap Build不允许插件勾子。

  • 同时安装了'branch-cordova-sdk'插件和'cordova-plugin-siri-shortcuts'插件后,深度链接接中断。当在Branch插件之后安装siri快捷方式插件时,这似乎经常发生。

    • 解决方案
      • 使用AppDelegate+SiriShortcuts 类别的修改版本来包含Branch。仅当存在Branch和SiriShortcuts时,此版本才有效。
      • 在Xcode工作区中,找到AppDelegate+BranchSDK.m 。删除它或忽略它。
      • 在Xcode工作区中,找到AppDelegate+SiriShortcuts.m 。这是我们要修改的文件。
      • 更新AppDelegate+SiriShortcuts.m 以调用Branch SDK。当两个SDK的当前版本一起使用时,此版本应该可用。
#import "AppDelegate+SiriShortcuts.h"
    #import <objectivec/runtime.h>

    #import "BranchNPM.h"

    #ifdef BRANCH_NPM
    #import "Branch.h"
    #else
    #import <Branch/Branch.h>
    #endif

    static void * UserActivityPropertyKey = &UserActivityPropertyKey;

    @implementation AppDelegate (siriShortcuts)

    - (NSUserActivity *)userActivity {
        return objectivec_getAssociatedObject(self, UserActivityPropertyKey);
    }

    - (void)setUserActivity:(NSUserActivity *)activity {
        objectivec_setAssociatedObject(self, UserActivityPropertyKey, activity, objectivec_ASSOCIATION_RETAIN_NONATOMIC);
    }

    - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler {

        // SiriShortcuts code
        NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
        if ([userActivity.activityType isEqualToString:[NSString stringWithFormat:@"%@.shortcut", bundleIdentifier]]) {
            self.userActivity = userActivity;
        }

        // Respond to Universal Links
        if (![[Branch getInstance] continueUserActivity:userActivity]) {
            // send unhandled URL to notification
            if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
                [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"BSDKPostUnhandledURL" object:[userActivity.webpageURL absoluteString]]];
            }
        }

        return YES;
    }

    // Respond to URI scheme links
    - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
        // pass the url to the handle deep link call
        if (![[Branch getInstance] application:app openURL:url options:options]) {
            // do other deep link routing for the Facebook SDK, Pinterest SDK, etc
            [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
            // send unhandled URL to notification
            [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"BSDKPostUnhandledURL" object:[url absoluteString]]];
        }
        return YES;
    }

    // Respond to Push Notifications
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
        @try {
            [[Branch getInstance] handlePushNotification:userInfo];
        }
        @catch (NSException *exception) {
            [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"BSDKPostUnhandledURL" object:userInfo]];
        }
    }

    @end

编译:Cordova错误

从SDK 2.5+迁移到3.0+

// Branch initialization
- Branch.initSession(function(data) {
+ Branch.initSession().then(function(data) {
if (data["+clicked_branch_link"]) {
// read deep link data on click
alert("Deep Link Data: " + JSON.stringify(data));
}
});

仅设备

  • 错误

ORIGINAL EXCEPTION: Branch is not defined

ReferenceError: Branch is not defined

  • 解决方案

    • Branch将打开并安装您的应用程序,因此您无法在桌面浏览器或模拟器中模拟Branch
// Ionic 2/3 - running on browser instead of device
if (!platform.is('cordova')) { return }
Branch.userCompletedAction('did_this')


// Ionic 2/3 - missing Branch import
const Branch = window['Branch'];

配给配置文件丢失

  • 错误

** ARCHIVE FAILED **

The following build commands failed:
Check dependencies
    (1 failure)
    Error: Error code 65 for command: xcodebuild with args: -xcconfig,cordova/build-debug.xcconfig,-workspace,Branch Testing.xcworkspace,-scheme,Branch Testing,-configuration,Debug,-destination,generic/platform=iOS,-archivePath,Branch Testing.xcarchive,archive,CONFIGURATION_BUILD_DIR=build/device,SHARED_PRECOMPS_DIR=build/sharedpch
No profiles for 'com.eneff.branch.cordova_testbed' were found
  • 解决方案

    • 通过在Xcode 打开您的应用并从那里启动(选择Provisioning Profile )进行修复

无效的bundle ID

  • 错误
An invalid value 'XC com eneff branch cordova_testbed' was provided for the parameter 'appIdName'.


Error: Error code 1 for command: /gradlew with args: cdvBuildDebug,-b,/build.gradle,-Dorg.gradle.daemon=true,-Pandroid.useDeprecatedNdk=true
  • 解决方案

    • 请不要选用cordovahyphens(机器人),或underscores(IOS)组合中的ID(widget ID)

文件未找到

  • 错误
Branch.h not found
  • 解决方案

    • 如果这是您看到的唯一错误,则可以通过升级依赖项来解决。确保您使用的是此插件的4.0.1或更高版本,并且已将Xcode,Cordova和其他依赖项(下面列出)更新为最新版本。由于CocoaPods和cordova-ios无法解决依赖关系而导致的此错误后来被修复。

    • 有时,当Pod项目中发生构建错误时,就会发生此错误。由于Branch通常是按字母顺序排列的第一个Pod,因此即使尝试构建主项目,它的错误也会显示为' ll(因为Pod没有构建' t),即使真正的错误在其他地方也是如此。确保阅读您的构建日志以查找阻止构建Pod项目的原始错误。

使用Pod构建失败

  • iOS构建因Pod和CONFIGURATION_BUILD_DIR配置而失败

  • 命令行生成会导致上述错误。请参阅“ 编译:电容器下面的部分,以获取CLI构建正常运行所需的最新依赖关系的完整列表。

编译:Cordova 8

  • 此插件的版本4.1.x与Cordova 8兼容,但是您需要在config.xml文件中添加一些字段:

  • Cordova 8不正确支持CocoaPods,此插件的4.x版本使用了CocoaPods。

  • 该插件可以' t包含pod规范的两个版本,这两个版本在Cordova 8和Cordova 9之间进行了更改。我们选择包含Cordova 9版本。

  • 为了支持Cordova 8 ' s处理CocoaPods,您必须安装一个额外的Cordova插件以正确合并我们的CocoaPod(从2020.02.10开始的" Branch " v.0.31.3)

  • 安装插件 cordova-plugin-cocoapods-support

  • 该插件不会向您的应用程序添加任何代码,严格来说,这是在构建应用程序之前创建Podfile的Cordova钩子。

  • 将以下行添加到config.xml中的widget/platform[name="ios"] 路径:

<preference name="pods_ios_min_version" value="<YOUR MINIMUM VALUE>" />
<pod name="Branch" spec="~> 0.31.3" />
  • <YOUR MINIMUM VALUE> 替换{1} 您的应用所需的最低iOS版本,例如" 8 "或" 10.0 "或" 11.4 "

  • 再次运行cordova prepare ios 并确保您看到类似于以下内容的控制台输出

Searching for new pods
Checking config.xml for pods.
config.xml requires pod: Branch
Installing pods
Sit back and relax this could take a while.
  • 如果下一节中列出的依赖关系是最新的(请参见编译:电容器 ),那么您也应该能够进行cordova build ios 而不会出现问题。

编译:电容器

  • 该插件的版本4.1.0可与Ionic 4 + Cordova和Ionic 4 + Capacitor一起使用,但需注意以下几点:

  • 我们强烈建议节点> = 10.15。节点8可能工作,但未经测试。

  • 对于科尔多瓦和电容器,您必须使用Xcode > = 11.1,CocoaPods > = 1.8.4,Cordova > = 8.0.0,Ionic-CLI > = 5.1,cordova-ios > = 5.1.0

    • 这些依赖项中的每一个都有可用于命令行构建的修补程序,并且pod依赖项解析可以正常工作
  • 您必须使用@ capacitor / ios > = 1.4.0。该版本之前的版本未将OpenURL通知与其他插件(包括Branch)联合。

  • use_frameworks 已从此插件中删除,现在将以静态方式构建。如果另一个Podfile使用use_frameworks 很好,但是此插件不再将其自身标记为动态。理想情况下,应更新您的应用以从Podfile中删除use_frameworks!

  • 使用电容器时,必须将以下条目自己添加到ios/App/App/Info.plist

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLName</key>
    <string>com.getcapacitor.capacitor</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>capacitor</string>
    </array>
  </dict>
  <dict>
    <key>CFBundleURLName</key>
    <string>branch-cordova-sdk</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>[YOUR URL SCHEME HERE]</string>
    </array>
  </dict>
</array>
<key>branch_key</key>
<string>[YOUR BRANCH LIVE KEY]</string>
<key>branch_app_domain</key>
<string>[YOUR DOMAIN].app.link</string>
  • 这是电容器的局限性,其中显式配置更改是开发人员'的责任,以避免"魔术配置"

  • 使用电容器时,您必须自己通过Xcode权利编辑器添加关联域权利

    • 这必须使用Xcode完成-再次,这是Capacitor '的核心理念的一部分,您可以控制每个配置文件的更改

    • 在Xcode中打开“ "签名&授权"选项卡,添加“关联的域”授权,然后添加在“分支”仪表板上找到的URL。

AppStore:iOS

  • 应用被拒绝,因为它使用推送通知功能,但未声明aps-environment密钥

  • 当branch-cordova-sdk转为使用CocoaPods时,Cordova 9中进行了更改,其中单独的授权文件不再放在一起。通过将分支配置直接添加到您现有的权利中,而不是创建新的权利文件,此插件的版本4.1.0中已解决此问题。此更改与Cordova 8向后兼容。

Apple搜索广告:iOS

更新25 天前

Cordova PhoneGap Ionic


建议的编辑仅限于API参考页

您只能建议对Markdown正文内容进行修改,而不能建议对API规范进行修改。