短いリファラーリンクの作成
ユーザー間のアトリビューションを可能にし、オーガニックな紹介からのアプリのインストールを追跡する、共有可能な短いリファラーリンクを生成します。
バージョン要件この機能を使用するには、SDKバージョン1.0.7以降が必要です。短いリンクは、作成後30日間有効です。
概要
ショートリファラーリンクとは
ショートリンクは、長い、パラメータいっぱいのシンギュラーリンクを、SMS、ソーシャルメディア、アプリ内招待で共有するのに便利な、コンパクトで安全なURLに変換します。
ショートリンクを動的に作成することで、ユーザーがお友達と共有し、アプリのダウンロードや使用を招待することができます。各ショートリンクは参照ユーザーを追跡するので、バイラルの成長を測定し、新規インストールを特定の支持者に帰属させることができます。
実装要件
必要なコンポーネント
ショートリファラーリンクを作成する前に、これらの要素を集めてください:
- 単一リンク:アプリのダウンロードにユーザーを誘導するベーストラッキングリンク。設定方法については、シンギュラーリンクのFAQを参照してください。
- 動的パラメータ:リンクにコンテキストを追加するオプションのカスタムパラメータ。トラッキングリンクパラメータで利用可能なオプションを見る
- リファラー情報:リンクを共有するユーザーの名前と ID を入力して、新規インストールのリファラーへの帰属を可能にします。
SDKメソッド
CreateReferrerShortLink
カスタムパラメータと成功およびエラー状態のコールバックハンドラを使用して、短いリファラーリンクを生成します。
メソッドのシグネチャ
static void createReferrerShortLink(
String baseLink,
String referrerName,
String referrerId,
Map<String, String> passthroughParams,
void Function(String? shortLinkURL, String? error) completionHandler
)
パラメータ:
- baseLink:元の Singular トラッキングリンクの URL。
- referrerName:参照元ユーザーの表示名
- referrerId:参照元ユーザーの一意な識別子
- passthroughParams:追加の動的パラメータを含むマップ (ない場合は空のマップを渡す)
-
completionHandler:パラメータを含むコールバック関数
(String? shortLinkURL, String? error)
メソッドの完全なドキュメントについてはcreateReferrerShortLink のリファレンスを参照ください。
基本的な使用例
カスタムパラメータでショートリンクを作成し、 成功コールバックで共有ロジックを実装します。
import 'package:flutter/material.dart';
import 'package:singular_flutter_sdk/singular.dart';
import 'package:share_plus/share_plus.dart';
class ReferralScreen extends StatelessWidget {
void handleShareReferral() {
// Create custom parameters for the link
final parameters = {
'channel': 'sms',
'campaign_id': 'summer_promo_2025',
'referral_type': 'friend_invite'
};
// Generate the short referrer link
Singular.createReferrerShortLink(
'https://sample.sng.link/D52wc/cuvk?pcn=test', // Base Singular Link
'John Doe', // Referrer name
'user_12345', // Referrer ID
parameters, // Custom parameters
(shortLink, error) {
if (error != null) {
// Error occurred during link creation
print('Error creating short link: $error');
_showErrorDialog('Failed to create share link. Please try again.');
} else if (shortLink != null) {
// Success - short link was created
print('Generated short link: $shortLink');
// Share the link using share_plus package
shareLink(shortLink);
}
}
);
}
void shareLink(String shortLink) {
try {
Share.share(
'Join me on this awesome app! $shortLink',
subject: 'App Invitation'
);
print('Link shared successfully');
} catch (error) {
print('Error sharing link: $error');
_showErrorDialog('Failed to share link');
}
}
void _showErrorDialog(String message) {
// Your dialog implementation
print('Error: $message');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Referral')),
body: Center(
child: ElevatedButton(
onPressed: handleShareReferral,
child: Text('Share Referral Link'),
),
),
);
}
}
高度な実装
再試行ロジック、ロード状態、クリップボードフォールバックを含む完全な紹介システムを実装します。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:singular_flutter_sdk/singular.dart';
import 'package:share_plus/share_plus.dart';
class ReferralManager extends StatefulWidget {
final String userId;
final String userName;
final String baseLink;
const ReferralManager({
Key? key,
required this.userId,
required this.userName,
required this.baseLink,
}) : super(key: key);
@override
_ReferralManagerState createState() => _ReferralManagerState();
}
class _ReferralManagerState extends State<ReferralManager> {
bool _isGenerating = false;
String? _lastGeneratedLink;
Future<String> _generateShortLink({int retryCount = 0}) async {
final parameters = {
'channel': 'in_app',
'campaign_id': 'organic_referral',
'user_tier': 'premium',
'referral_timestamp': DateTime.now().millisecondsSinceEpoch.toString()
};
final completer = Completer<String>();
Singular.createReferrerShortLink(
widget.baseLink,
widget.userName,
widget.userId,
parameters,
(shortLink, error) async {
if (error != null) {
// Retry logic with exponential backoff
if (retryCount < 3) {
final delay = Duration(seconds: (1 << retryCount)); // 1s, 2s, 4s
print('Retrying in ${delay.inSeconds}s... (Attempt ${retryCount + 1}/3)');
await Future.delayed(delay);
try {
final result = await _generateShortLink(retryCount: retryCount + 1);
completer.complete(result);
} catch (e) {
completer.completeError(e);
}
} else {
completer.completeError(Exception(error));
}
} else if (shortLink != null) {
setState(() {
_lastGeneratedLink = shortLink;
});
completer.complete(shortLink);
} else {
completer.completeError(Exception('Unknown error occurred'));
}
}
);
return completer.future;
}
Future<void> _handleShare() async {
setState(() {
_isGenerating = true;
});
try {
final shortLink = await _generateShortLink();
print('Short link generated: $shortLink');
// Attempt to share
await Share.share(
'${widget.userName} invited you to join! $shortLink',
subject: 'App Invitation from ${widget.userName}'
);
// Track share event
Singular.event('referral_link_shared');
print('Link shared successfully');
} catch (error) {
print('Error in share flow: $error');
// Fallback: Copy to clipboard if available
if (_lastGeneratedLink != null) {
await Clipboard.setData(ClipboardData(text: _lastGeneratedLink!));
_showDialog(
'Link Copied',
'Failed to share, but the referral link has been copied to your clipboard!',
);
} else {
_showDialog(
'Error',
'Failed to generate referral link. Please check your connection and try again.',
);
}
} finally {
setState(() {
_isGenerating = false;
});
}
}
Future<void> _copyToClipboard() async {
if (_lastGeneratedLink != null) {
await Clipboard.setData(ClipboardData(text: _lastGeneratedLink!));
_showDialog('Copied!', 'Referral link copied to clipboard');
} else {
_showDialog('No Link', 'Please generate a link first');
}
}
void _showDialog(String title, String message) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(title),
content: Text(message),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('OK'),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (_isGenerating)
CircularProgressIndicator()
else ...[
ElevatedButton(
onPressed: _handleShare,
child: Text('Share Referral Link'),
),
if (_lastGeneratedLink != null) ...[
SizedBox(height: 16),
OutlinedButton(
onPressed: _copyToClipboard,
child: Text('Copy Link'),
),
],
],
],
);
}
}
実装のベストプラクティス
エラー処理
ネットワーク障害、無効なパラメータ、またはサーバーの問題を管理するために、コールバックに堅牢なエラー処理を実装します。
- 再試行ロジック:一過性のネットワークエラーに対する指数関数的バックオフを実装します。
- ユーザー・フィードバック:リンク作成失敗時に明確なエラーメッセージを表示
- フォールバック・オプション:代替共有方法の提供(例:短いリンク作成に失敗した場合、完全なシンギュラーリンクを共有する)
-
検証:問題を早期に発見するために、
createReferrerShortLinkを呼び出す前にパラメータを検証します。
トラッキングと分析
リファラー情報を活用して、バイラルループを構築し、オーガニックな成長を測定する。
ベストプラクティス社内のユーザー識別システムと一致する一貫したリファラーIDを使用する。これにより、次のことが可能になります:
- 新規インストールを特定の参照ユーザーに帰属させる。
- 紹介に成功したユーザーに報酬を与える
- バイラル係数とKファクターメトリクスの追跡
- 最も価値のあるブランド支持者を特定
リンクの有効期限
共有戦略において、30日間のリンクライフサイクルを計画する。
重要:ショートリンクは30日で失効します。長期的なキャンペーンや永続的な共有機能の場合は、定期的に新しいショートリンクを生成するか、予備として完全なシンギュラーリンクを使用してください。
一般的な使用例
アプリ内紹介プログラム
パーソナライズされた紹介リンクを使って、ユーザーがアプリから直接友達を招待できるようにします。
- 報酬システム:紹介者を追跡し、友達登録に成功したユーザーに報酬を与えます。
- ソーシャル共有:SMS、WhatsApp、Eメール、ソーシャルメディア用のshare_plusパッケージと統合します。
- パーソナライズされた招待:パーソナライズするために紹介者の名前を共有メッセージに含めることができます。
ユーザー生成コンテンツ
ユーザーが他のユーザーと共有したいコンテンツを作成した場合、共有可能なリンクを作成します。
- コンテンツのアトリビューション:どのコンテンツが最もアプリのインストールを促進したかを追跡
- クリエイターの認識:新規ユーザーをコンテンツ作成者に帰属させ、ゲーミフィケーションを実現します。
- キャンペーンタグ付け:コンテンツの種類やカテゴリーに基づいた動的なパラメータを追加
イベント招待
どの出席者が新規ユーザーを連れてきたかを追跡するイベント招待用のユニークなリンクを生成します。
- イベントコンテキスト:リンクパラメータにイベントIDと詳細を含める
- 参加者のトラッキング:イベントからイベントへのバイラル拡散を測定
- ネットワーク効果:コンバージョン率の高いイベントを特定