Zaproś użytkowników do swojej aplikacji

Jednym z najskuteczniejszych sposobów na zachęcenie nowych użytkowników do zainstalowania Twojej aplikacji jest umożliwienie użytkownikom udostępniania treści z Twojej aplikacji znajomym. Dzięki Dynamic Links możesz stworzyć wspaniałe środowisko udostępniania między użytkownikami: użytkownicy, którzy otrzymują rekomendacje treści od swoich znajomych, mogą kliknąć łącze i przejść bezpośrednio do udostępnianych treści w Twojej aplikacji, nawet jeśli muszą przejść do aplikacji Sklep lub Sklep Google Play, aby najpierw zainstalować aplikację.

Łącząc trwałość skierowań użytkowników i trwałość linków dynamicznych, możesz tworzyć funkcje udostępniania i polecania między użytkownikami, które przyciągają nowych użytkowników, przyciągając ich bezpośrednio do treści Twojej aplikacji lub wyświetlając promocje, które przynoszą obopólne korzyści osobie polecającej i polecanej. .

Kluczowe korzyści

  • Nowi użytkownicy otwierający Twoją aplikację po raz pierwszy otrzymują spersonalizowane środowisko pierwszego uruchomienia, które jest kontekstualizowane na podstawie tego, co ich znajomy chciał im udostępnić. Na przykład możesz wyświetlić treść, która została im udostępniona, lub automatycznie połączyć ich z przyjacielem, który ich zaprosił.
  • Ułatwia użytkownikom udostępnianie treści znajomym na różnych platformach, niezależnie od tego, czy ich znajomi mają zainstalowaną Twoją aplikację, czy nie.

Oto jak zacząć!

Utwórz nowy projekt Firebase i zainstalować dynamiczne linki SDK w swojej aplikacji.

Zainstalowanie pakietu SDK linków dynamicznych umożliwia Firebase przekazywanie do aplikacji danych dotyczących linku dynamicznego, także po zainstalowaniu aplikacji przez użytkownika.

Teraz nadszedł czas na skonfigurowanie linków, które użytkownicy będą mogli wysyłać swoim znajomym. Nie martw się, jeśli znajomi Twoich użytkowników nie mają jeszcze zainstalowanej aplikacji; Dynamic Links może się tym zająć.

Dla każdego elementu treści, którą chcesz być współdzielone, stworzyć Dynamic Link .

Podczas tworzenia Dynamic Link, musisz dostarczyć HTTP lub HTTPS URL jako link parametr, który będzie używany do identyfikacji zawartości jesteś udostępniania. Jeśli masz witrynę z równoważną zawartością, użyj adresów URL swojej witryny. Zapewni to prawidłowe renderowanie tych linków na platformie, która nie obsługuje Linków dynamicznych, takiej jak przeglądarka komputerowa. Na przykład:

https://example.page.link/?link=https://www.example.com/content?item%3D1234&apn=com.example.android&ibi=com.example.ios&isi=12345

Możesz również dodać dodatkowe informacje do ładunku danych, dodając parametry zakodowane w adresie URL — na przykład w celu wskazania, że ​​łącze jest przeznaczone dla konkretnego użytkownika, na przykład w zaproszeniu do gry.

https://example.page.link/?link=https://www.example.com/invitation?gameid%3D1234%26referrer%3D555&apn=com.example.android&ibi=com.example.ios&isi=12345

Przed udostępnieniem tych linków, możesz użyć Firebase dynamiczne linki URL Shortener API do generowania bardziej przyjaznych wyglądające adresy URL. Krótkie wygląd Dynamic Link, jak w poniższym przykładzie:

https://example.page.link/WXYZ

Niezależnie od tego, odwołuje się użyć, gdy użytkownik otworzy Dynamic Link na swoim urządzeniu, aplikacja określony przez apn parametru (na Androidzie) lub ibi i isi parametrów (na iOS) odbędzie użytkownikom Play Store lub App Store, aby zainstalować aplikację jeśli nie jest jeszcze zainstalowany. Następnie, gdy aplikacja jest instalowana i otwierana, adres URL określony w parametrze „link” jest przekazywany do aplikacji.

Najpierw spójrz na ten prosty przykład aplikacji do czatu opartej na pokojach, takiej jak Hangouts, która generuje linki zapraszające osoby do pokojów czatu.

iOS

chat app screenshotchat app screenshot with share sheet

Android

chat app screenshotchat app screenshot with share sheet

Szybki

func generateContentLink() -> URL {
  let baseURL = URL(string: "https://your-custom-name.page.link")!
  let domain = "https://your-app.page.link"
  let linkBuilder = DynamicLinkComponents(link: baseURL, domainURIPrefix: domain)
  linkBuilder?.iOSParameters = DynamicLinkIOSParameters(bundleID: "com.your.bundleID")
  linkBuilder?.androidParameters =
      DynamicLinkAndroidParameters(packageName: "com.your.packageName")


  // Fall back to the base url if we can't generate a dynamic link.
  return linkBuilder?.link ?? baseURL
}

Cel C

- (NSURL *)generateContentLink {
  NSURL *baseURL = [NSURL URLWithString:@"https://your-custom-name.page.link"];
  NSString *domain = @"https://your-app.page.link";
  FIRDynamicLinkComponents *builder = [[FIRDynamicLinkComponents alloc] initWithLink:baseURL domainURIPrefix:domain];
  builder.iOSParameters = [FIRDynamicLinkIOSParameters parametersWithBundleID:@"com.your.bundleID"];
  builder.androidParameters = [FIRDynamicLinkAndroidParameters parametersWithPackageName:@"com.your.packageName"];

  // Fall back to the base url if we can't generate a dynamic link.
  return builder.link ?: baseURL;
}

Jawa

public static Uri generateContentLink() {
    Uri baseUrl = Uri.parse("https://your-custom-name.page.link");
    String domain = "https://your-app.page.link";

    DynamicLink link = FirebaseDynamicLinks.getInstance()
            .createDynamicLink()
            .setLink(baseUrl)
            .setDomainUriPrefix(domain)
            .setIosParameters(new DynamicLink.IosParameters.Builder("com.your.bundleid").build())
            .setAndroidParameters(new DynamicLink.AndroidParameters.Builder("com.your.packageName").build())
            .buildDynamicLink();

    return link.getUri();
}

Kotlin+KTX

fun generateContentLink(): Uri {
    val baseUrl = Uri.parse("https://your-custom-name.page.link")
    val domain = "https://your-app.page.link"

    val link = FirebaseDynamicLinks.getInstance()
            .createDynamicLink()
            .setLink(baseUrl)
            .setDomainUriPrefix(domain)
            .setIosParameters(DynamicLink.IosParameters.Builder("com.your.bundleid").build())
            .setAndroidParameters(DynamicLink.AndroidParameters.Builder("com.your.packageName").build())
            .buildDynamicLink()

    return link.uri
}

Po utworzeniu dynamicznego linku możesz dodać przycisk udostępniania do interfejsu użytkownika, który uruchomi standardowy przepływ udostępniania platformy:

Szybki

lazy private var shareController: UIActivityViewController = {
  let activities: [Any] = [
    "Learn how to share content via Firebase",
    URL(string: "https://firebase.google.com")!
  ]
  let controller = UIActivityViewController(activityItems: activities,
                                            applicationActivities: nil)
  return controller
}()

@IBAction func shareButtonPressed(_ sender: Any) {
  let inviteController = UIStoryboard(name: "Main", bundle: nil)
    .instantiateViewController(withIdentifier: "InviteViewController")
  self.navigationController?.pushViewController(inviteController, animated: true)
}

Cel C

- (UIActivityViewController *)shareController {
  if (_shareController == nil) {
    NSArray *activities = @[
      @"Learn how to share content via Firebase",
      [NSURL URLWithString:@"https://firebase.google.com"]
    ];
    UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:activities applicationActivities:nil];
    _shareController = controller;
  }
  return _shareController;
}

- (IBAction)shareLinkButtonPressed:(UIView *)sender {
  if (![sender isKindOfClass:[UIView class]]) {
    return;
  }

  self.shareController.popoverPresentationController.sourceView = sender;
  [self presentViewController:self.shareController animated:YES completion:nil];
}

Jawa

private void onShareClicked() {
    Uri link = DynamicLinksUtil.generateContentLink();

    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("text/plain");
    intent.putExtra(Intent.EXTRA_TEXT, link.toString());

    startActivity(Intent.createChooser(intent, "Share Link"));
}

Kotlin+KTX

private fun onShareClicked() {
    val link = DynamicLinksUtil.generateContentLink()

    val intent = Intent(Intent.ACTION_SEND)
    intent.type = "text/plain"
    intent.putExtra(Intent.EXTRA_TEXT, link.toString())

    startActivity(Intent.createChooser(intent, "Share Link"))
}

W tym przykładzie domyślny interfejs udostępniania automatycznie przedstawia listę aplikacji do udostępniania linku, więc jest to coś, co możesz skonfigurować we własnej aplikacji za pomocą zaledwie kilku wierszy kodu.

Zamiast zmuszać użytkownika do wybierania kontaktów i tworzenia wiadomości w aplikacji, te akcje są delegowane do aplikacji, którą wybiera z okna dialogowego udostępniania. Ponadto delegowanie udostępniania innym aplikacjom oznacza, że ​​nie musisz prosić użytkownika o uprawnienia do kontaktów i pozwala użytkownikom wybierać z rozwiniętej listy kontaktów w wybranej aplikacji. Aby lepiej ułatwienia podziału społecznego, można dodać podglądu metadanych social media do dynamicznego łącza, które będą wyświetlane wraz z linkiem w głównych kanałach społecznościowych.

Czasami jednak samo wysłanie samego linku bez tekstu nie wystarcza do uzyskania atrakcyjnego polecenia. Dołączając do linku krótką wiadomość i, jeśli to możliwe, bogatszą prezentację, użytkownicy mogą zrozumieć propozycję wartości osoby polecającej, gdy ją otrzymają:

iOS

rewarded referral screenshotrewarded referral screenshot with share sheet

Android

rewarded referral screenshotrewarded referral screenshot with share sheet

Chociaż jest to bardziej złożone niż w poprzednim przykładzie, podejście będzie mniej więcej takie samo. Na tym ekranie znajduje się duża grafika z propozycją wartości zaproszenia i przyciskami do udostępniania w głównych kanałach społecznościowych. W tym przepływie interfejsu użytkownika występuje pewna nadmiarowość — niektóre kanały udostępniania są prezentowane indywidualnie, aby umożliwić bardziej specyficzne dla kanału dostosowanie wiadomości, na przykład dodanie wiersza tematu do zaproszeń e-mail. W tym menu zaproszeń:

  • Prezentuj przyciski udostępniania e-maili, wiadomości tekstowych i kopiowania linków oraz odpowiednio dostosuj ich wiadomości. Wiadomość e-mail będzie zawierać temat i może zawierać dłuższą treść z podziałami wierszy, obrazami i białymi znakami; tekst powinien zawierać krótszą treść z podziałami wierszy, ale z małą ilością spacji i bez obrazów; a kopiowanie linków powinno po prostu skopiować link i nic więcej.
  • Użyj interfejsu udostępniania systemu do wszystkich innych czynności, w tym krótkiego zaproszenia do dołączenia do łącza.
  • Głęboki link za pomocą schematu adresu URL lub uniwersalny link do innej aplikacji, która ma specjalną logikę obsługi zaproszeń do Twojej aplikacji. To nie zadziała poza partnerstwem między Twoją organizacją a inną aplikacją i prawdopodobnie nie jest opcją dla mniejszych organizacji. To powiedziawszy, niektóre aplikacje mogą publicznie dokumentować swoje uniwersalne/głębokie zachowanie linkowania. W naszym przykładzie zaimplementujemy fikcyjną wersję tego.

Najpierw zdefiniuj typ zawartości zaproszenia, który zawiera tylko informacje w zaproszeniu i nie zawiera żadnych funkcji. W ten sposób możesz zacząć od typów danych i myśleć o swoim kodzie pod kątem tego, w jaki sposób łączy te dane.

Szybki

/// The content within an invite, with optional fields to accommodate all presenters.
/// This type could be modified to also include an image, for sending invites over email.
struct InviteContent {

  /// The subject of the message. Not used for invites without subjects, like text message invites.
  var subject: String?

  /// The body of the message. Indispensable content should go here.
  var body: String?

  /// The URL containing the invite. In link-copy cases, only this field will be used.
  var link: URL

}

Cel C

/// The content within an invite, with optional fields to accommodate all presenters.
/// This type could be modified to also include an image, for sending invites over email.
@interface InviteContent : NSObject <NSCopying>

/// The subject of the message. Not used for invites without subjects, like text message invites.
@property (nonatomic, readonly, nullable) NSString *subject;

/// The body of the message. Indispensable content should go here.
@property (nonatomic, readonly, nullable) NSString *body;

/// The URL containing the invite. In link-copy cases, only this field will be used.
@property (nonatomic, readonly) NSURL *link;

- (instancetype)initWithSubject:(nullable NSString *)subject
                           body:(nullable NSString *)body
                           link:(NSURL *)link NS_DESIGNATED_INITIALIZER;

- (instancetype)init NS_UNAVAILABLE;

@end

Jawa

/**
 * The content of an invitation, with optional fields to accommodate all presenters.
 * This type could be modified to also include an image, for sending invites over email.
 */
public class InviteContent {

    /**
     * The subject of the message. Not used for invites without subjects, like SMS.
     **/
    @Nullable
    public final String subject;

    /**
     * The body of the message. Indispensable content should go here.
     **/
    @Nullable
    public final String body;

    /**
     * The URL containing the link to invite. In link-copy cases, only this field will be used.
     **/
    @NonNull
    public final Uri link;

    public InviteContent(@Nullable String subject, @Nullable String body, @NonNull Uri link) {
        // ...
    }

}

Kotlin+KTX

/**
 * The content of an invitation, with optional fields to accommodate all presenters.
 * This type could be modified to also include an image, for sending invites over email.
 */
data class InviteContent(
    /** The subject of the message. Not used for invites without subjects, like SMS.  */
    val subject: String?,
    /** The body of the message. Indispensable content should go here.  */
    val body: String?,
    /** The URL containing the link to invite. In link-copy cases, only this field will be used.  */
    val link: Uri
)

Jedynym wymaganym tutaj elementem danych jest adres URL, bez którego nie można zapraszać użytkowników do swojej aplikacji. Pozostałe dane są wyraźnie ustrukturyzowane pod kątem wysyłania wiadomości e-mail, co sprawia, że ​​w niektórych innych przypadkach są nieco niezręczne — podczas wysyłania zaproszenia za pośrednictwem tekstu notka towarzysząca linkowi może być odczytywana podobnie do tematu wiadomości e-mail, ale podczas udostępniania w mediach społecznościowych link towarzyszący tekstowi może bardziej przypominać treść wiadomości e-mail. Będziesz musiał poeksperymentować z tym siebie, aby znaleźć najlepszą równowagę dla swojej aplikacji, a jeśli nie masz pewności, zawsze można skorzystać z usługi jak Remote Config , aby umożliwić zmianę wartości tekstowe po uruchomieniu aplikacji.

Szybki

/// A type responsible for presenting an invite given using a specific method
/// given the content of the invite.
protocol InvitePresenter {

  /// The name of the presenter. User-visible.
  var name: String { get }

  /// An icon representing the invite method. User-visible.
  var icon: UIImage? { get }

  /// Whether or not the presenter's method is available. iOS devices that aren't phones
  /// may not be able to send texts, for example.
  var isAvailable: Bool { get }

  /// The content of the invite. Some of the content type's fields may be unused.
  var content: InviteContent { get }

  /// Designated initializer.
  init(content: InviteContent, presentingController: UIViewController)

  /// This method should cause the presenter to present the invite and then handle any actions
  /// required to complete the invite flow.
  func sendInvite()

}

Cel C

/// A type responsible for presenting an invite given using a specific method
/// given the content of the invite.
@protocol InvitePresenter <NSObject>

/// The name of the presenter. User-visible.
@property (nonatomic, readonly) NSString *name;

/// An icon representing the invite method. User-visible.
@property (nonatomic, readonly, nullable) UIImage *icon;

/// Whether or not the presenter's method is available. iOS devices that aren't phones
/// may not be able to send texts, for example.
@property (nonatomic, readonly) BOOL isAvailable;

/// The content of the invite. Some of the content type's fields may be unused.
@property (nonatomic, readonly) InviteContent *content;

/// Designated initializer.
- (instancetype)initWithContent:(InviteContent *)content presentingViewController:(UIViewController *)controller;

/// This method should cause the presenter to present the invite and then handle any actions
/// required to complete the invite flow.
- (void)sendInvite;

@end

Jawa

/**
 * Presents the invite using a specific method, such as email or social.
 */
public class InvitePresenter {

    /**
     * The user-visible name of the invite method, like 'Email' or 'SMS'
     **/
    public final String name;

    /**
     * An icon representing the invite method.
     **/
    @DrawableRes
    public final int icon;

    /**
     * Whether or not the method is available on this device. For example, SMS is phone only.
     **/
    public final boolean isAvailable;

    /**
     * The Content of the invitation
     **/
    public final InviteContent content;

    public InvitePresenter(String name, @DrawableRes int icon, boolean isAvailable, InviteContent content) {
        // ...
    }

    /**
     * Send the invitation using the specified method.
     */
    public void sendInvite(Context context) {
        // ...
    }

}

Kotlin+KTX

/**
 * Presents the invite using a specific method, such as email or social.
 */
open class InvitePresenter(
    /** The user-visible name of the invite method, like 'Email' or 'SMS'  */
    val name: String,
    /** An icon representing the invite method.  */
    @param:DrawableRes @field:DrawableRes
    val icon: Int,
    /** Whether or not the method is available on this device. For example, SMS is phone only.  */
    val isAvailable: Boolean,
    /** The Content of the invitation  */
    val content: InviteContent
) {
    /**
     * Send the invitation using the specified method.
     */
    open fun sendInvite(context: Context) {
        // ...
    }
}

Teraz wszystko, co pozostało, to podłączyć to do wybranego komponentu interfejsu użytkownika. Dla pełnej realizacji tego przepływu zaprosić zobaczyć próbki na GitHub dla iOS i Androida .

Są to wszystkie metody umożliwiające użytkownikom wysyłanie zaproszeń do znajomych, co jest najlżejszym rozwiązaniem zaproszeń. Wiele popularnych aplikacji dostarcza również zaproszenia, wysyłając wiadomości e-mail za pośrednictwem własnego zaplecza, co wymaga zintegrowania usługi wysyłania poczty, ale oferuje szereg korzyści, które nie są dostępne w inny sposób, z kilkoma drobnymi wadami.

Plusy:

  • Włącza wiadomości e-mail ze złożonymi znacznikami, których użytkownik nie może modyfikować przed wysłaniem.
  • Umożliwia bardziej szczegółowe śledzenie/analizę (tj. wysyłanie sukcesów i niepowodzeń na zapleczu).

Cons:

  • E-maile z większym prawdopodobieństwem zostaną oznaczone jako spam
  • Wymaga integracji z usługą dostarczania poczty e-mail
  • Wymaga uprawnień do kontaktów w aplikacji

Ogólnie rzecz biorąc, wysyłanie zaproszeń za pośrednictwem własnej usługi dostarczania poczty e-mail zapewnia bardziej spójne i potencjalnie bogatsze środowisko zaproszeń kosztem wszechstronności.

Otwórz połączoną zawartość w swojej aplikacji

Na koniec musisz otrzymać link, który jest przekazywany do Twojej aplikacji, aby móc wyświetlić połączoną treść odbiorcy. Jest to łatwe dzięki SDK Dynamic Links:

iOS

Na iOS, pojawi się Dynamic Link poprzez wdrożenie application:continueUserActivity:restorationHandler: metody. W obsługi przywracania można uzyskać Dynamic Link wywołując handleUniversalLink:completion: . Jeśli Dynamic Link został przekazany do aplikacji, można go pobrać z url własność FIRDynamicLink . Na przykład:

Cel C

[[FIRDynamicLinks dynamicLinks]
    handleUniversalLink:userActivity.webpageURL
             completion:^(FIRDynamicLink * _Nullable dynamicLink,
                          NSError * _Nullable error) {
      NSString *link = dynamicLink.url;
      BOOL strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong;
      // ...
    }];

Szybki

FIRDynamicLinks.dynamicLinks()?.handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in
    let link = dynamicLink.url
    let strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong
    // ...
}

Dodatkowo, należy zadzwonić dynamicLinkFromCustomSchemeURL: w application:openURL:options: metody otrzymywania dynamiczne linki przekazane do aplikacji jako URL Schemat niestandardowy. Na przykład:

Cel C

FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url];
if (dynamicLink) {
  NSString *link = dynamicLink.url;
  BOOL strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong;
  // ...
  return YES;
}

Szybki

let dynamicLink = FIRDynamicLinks.dynamicLinks()?.dynamicLinkFromCustomSchemeURL(url)
if let dynamicLink = dynamicLink {
  let link = dynamicLink.url
  let strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong
  // ...
  return true
}

Teraz, że masz wartość link parametru można wyświetlić połączonego treści do odbiorcy, lub przetwarzać dane określone przez parametr w jakiś inny sposób. URL trasy biblioteki takie jak JLRoutes mogą pomóc w tym zadaniu.

Jeśli otrzymujesz link przeznaczona dla konkretnego odbiorcy, należy upewnić się, że dynamiczny Link zaufanie mecz jest strong przed uruchomieniem jakiegokolwiek użytkownika specyficzną logikę.

Android

Na Androidzie użyć getDynamicLink() metodę, aby uzyskać dane z Dynamic Link:

Jawa

FirebaseDynamicLinks.getInstance()
        .getDynamicLink(getIntent())
        .addOnCompleteListener(new OnCompleteListener<PendingDynamicLinkData>() {
            @Override
            public void onComplete(@NonNull Task<PendingDynamicLinkData> task) {
                if (!task.isSuccessful()) {
                    // Handle error
                    // ...
                }

                FirebaseAppInvite invite = FirebaseAppInvite.getInvitation(task.getResult());
                if (invite != null) {
                    // Handle invite
                    // ...
                }
            }
        });

Kotlin+KTX

Firebase.dynamicLinks
        .getDynamicLink(intent)
        .addOnCompleteListener { task ->
            if (!task.isSuccessful) {
                // Handle error
                // ...
            }

            val invite = FirebaseAppInvite.getInvitation(task.result)
            if (invite != null) {
                // Handle invite
                // ...
            }
        }

Teraz, że masz wartość link parametru można wyświetlić połączonego treści do odbiorcy, lub przetwarzać dane określone przez parametr w jakiś inny sposób. W tym zadaniu może pomóc biblioteka do routingu adresów URL.