Skip to content

Commit b5d5b20

Browse files
afgieladvaith1colinloretz
authored
[guides] add Prompting Users to Share Incentivized Links Guide (#7342)
* [guides] add Prompting Users to Share Incentivized Links Guide * slight clarification on auto referredId * another copy tweak * rework for clarity, add sections * implement some feedback * Update docs/activities/Development_Guides.mdx Co-authored-by: advaith <[email protected]> * Apply suggestions from code review Co-authored-by: Colin Loretz <[email protected]> * :s/referer/referrer/g * :%s/DiscordRPC/discordSdk/g --------- Co-authored-by: advaith <[email protected]> Co-authored-by: Colin Loretz <[email protected]>
1 parent e4bc486 commit b5d5b20

File tree

1 file changed

+93
-4
lines changed

1 file changed

+93
-4
lines changed

docs/activities/Development_Guides.mdx

Lines changed: 93 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ These guides include suggested development practices, SDK commands, and user flo
9696
</Card>
9797
</Container>
9898

99+
## Growth and Referrals
100+
<Container>
101+
<Card title="Prompting Users to Share Incentivized Links" link="#DOCS_ACTIVITIES_DEVELOPMENT_GUIDES/prompting-users-to-share-incentivized-links">
102+
Encourage your users to share links to your activity by adding tracking and offering rewards for engagement.
103+
</Card>
104+
</Container>
105+
99106
## Assets & Metadata
100107
<Container>
101108
<Card title="Setting Up Activity Metadata" link="#DOCS_ACTIVITIES_DEVELOPMENT_GUIDES/setting-up-activity-metadata">
@@ -812,7 +819,7 @@ Here's a basic example for retrieving a user's avatar and username
812819

813820
```javascript
814821
// We'll be referencing the user object returned from authenticate
815-
const {user} = await DiscordRPC.commands.authenticate({
822+
const {user} = await discordSdk.commands.authenticate({
816823
access_token: accessToken,
817824
});
818825

@@ -839,13 +846,13 @@ Here's an example of how to retrieve the user's guild-specific avatar and nickna
839846
840847
```javascript
841848
// We'll be referencing the user object returned from authenticate
842-
const {user} = await DiscordRPC.commands.authenticate({
849+
const {user} = await discordSdk.commands.authenticate({
843850
access_token: accessToken,
844851
});
845852

846853
// When using the proxy, you may instead replace `https://discord.com` with `/discord`
847854
// or whatever url mapping you have chosen via the developer portal
848-
fetch(`https://discord.com/api/users/@me/guilds/${DiscordRPC.guildId}/member`, {
855+
fetch(`https://discord.com/api/users/@me/guilds/${discordSdk.guildId}/member`, {
849856
method: 'GET',
850857
headers: {
851858
Authorization: `Bearer ${accessToken}`,
@@ -858,7 +865,7 @@ fetch(`https://discord.com/api/users/@me/guilds/${DiscordRPC.guildId}/member`, {
858865
let guildAvatarSrc = '';
859866
// Retrieve the guild-specific avatar, and fallback to the user's avatar
860867
if (guildsMembersRead?.avatar) {
861-
guildAvatarSrc = `https://cdn.discordapp.com/guilds/${DiscordRPC.guildId}/users/${user.id}/avatars/${guildsMembersRead.avatar}.png?size=256`;
868+
guildAvatarSrc = `https://cdn.discordapp.com/guilds/${discordSdk.guildId}/users/${user.id}/avatars/${guildsMembersRead.avatar}.png?size=256`;
862869
} else if (user.avatar) {
863870
guildAvatarSrc = `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png?size=256`;
864871
} else {
@@ -879,6 +886,88 @@ This example is being done entirely on the client, however, a more common patter
879886
880887
---
881888
889+
### Prompting Users to Share Incentivized Links
890+
891+
Incentivized sharing can help grow your Activity through network effects. This guide covers implementing a reward system for users who share links and those who click them.
892+
893+
#### Implementation Overview
894+
1. Create and track an incentivized link for a promotional campaign, then prompt users to share the link
895+
2. Handle incoming referrals and grant valid rewards
896+
897+
#### Sharing Links
898+
899+
When implementing sharing, you'll need to:
900+
1. Generate a unique ID for tracking the promotion
901+
2. Call the [`shareLink`](#DOCS_DEVELOPER_TOOLS_EMBEDDED_APP_SDK/sharelink) command
902+
3. Track the share attempt
903+
904+
```javascript
905+
// Generate a unique ID for this promotion
906+
// This could be per-campaign, per-user, or per-share depending on your needs
907+
const customId = await createPromotionalCustomId();
908+
909+
try {
910+
const { success } = await discordSdk.commands.shareLink({
911+
message: 'Click this link to redeem 5 free coins!',
912+
custom_id: customId,
913+
// referrer_id is optional - if omitted, the current user's ID is used
914+
});
915+
916+
if (success) {
917+
// Track successful share for analytics/limiting
918+
await trackSuccessfulShare(customId);
919+
}
920+
} catch (error) {
921+
// Handle share failures appropriately
922+
console.error('Failed to share link:', error);
923+
}
924+
```
925+
926+
#### Handling Incoming Referrals
927+
When a user clicks a shared link, your activity will launch with referral data available through the SDK:
928+
929+
```javascript
930+
// Early in your activity's initialization
931+
async function handleReferral() {
932+
// Validate the referral data
933+
if (!discordSdk.customId || !discordSdk.referrerId) {
934+
return;
935+
}
936+
937+
try {
938+
// Verify this is a valid promotion and hasn't expired
939+
const promotion = await validatePromotion(discordSdk.customId);
940+
if (!promotion) {
941+
console.log('Invalid or expired promotion');
942+
return;
943+
}
944+
945+
// Prevent self-referrals
946+
if (discordSdk.referrerId === currentUserId) {
947+
console.log('Self-referrals not allowed');
948+
return;
949+
}
950+
951+
// Grant rewards to both users
952+
await grantRewards({
953+
promotionId: discordSdk.customId,
954+
referrerId: discordSdk.referrerId,
955+
newUserId: currentUserId
956+
});
957+
} catch (error) {
958+
console.error('Failed to process referral:', error);
959+
}
960+
}
961+
```
962+
963+
#### Link Sharing Best Practices
964+
- Generate unique, non-guessable `customId`s
965+
- Track and validate referrals to prevent abuse
966+
- Handle edge cases like expired promotions gracefully
967+
- Consider implementing cool-down periods between shares
968+
969+
---
970+
882971
### Preventing unwanted activity sessions
883972
884973
Activities are surfaced through iframes in the Discord app. The activity website itself is publicly reachable at `<application_id>.discordsays.com`. Activities will expect to be able to communicate with Discord's web or mobile client via the Discord SDK's RPC protocol. If a user loads the activity's website in a normal browser, the Discord RPC server will not be present, and the activity will likely fail in some way.

0 commit comments

Comments
 (0)