|
| 1 | +--- |
| 2 | +sidebar_label: Growth and Referrals |
| 3 | +--- |
| 4 | + |
| 5 | +[Home](/docs/intro) > [Activities](/docs/activities/overview) > [Development Guides](/docs/activities/development-guides) > {sidebar_label} |
| 6 | + |
| 7 | +# Growth and Referrals |
| 8 | + |
| 9 | +## Prompting Users to Share Incentivized Links |
| 10 | + |
| 11 | +Incentivized sharing can help grow your Activity through network effects. You can use links in several different ways such as: |
| 12 | + |
| 13 | +- **Referral links.** Users can copy referral links inside your Activity, which include their Discord user ID (`https://discord.com/activities/<your Activity ID>?referrer_id=123456789`), and they can send to their friends. If their friend accepts and starts playing your game, then you gift the referrer something inside your game. |
| 14 | +- **Promotions.** You can run a temporary promotion on social media, where you offer a reward if they start playing now. Share a custom link on your social media (`https://discord.com/activities/<your Activity ID>?custom_id=social012025` ). Anyone who clicks that specific link receives something inside your game. |
| 15 | +- **Social deep-links.** Currently, when users launch an Activity, they all land in the same place. Instead, you can start deep-linking to contextually relevant points in your game. For example, user A can copy a link inside your Activity for engaging other users (`https://discord.com/activities/<your Activity ID>?referrer_id=123456789&custom_id=visit-location`), and sends the link to their friends in a DM or channel. Then, user B who clicks the link gets taken directly to user A’s location. |
| 16 | +- **Turn-based deep-links.** When you send an “it’s your turn” DM to a user, you can include a link which takes them directly to the right game instance and the turn they need to take. |
| 17 | +- **Affiliate marketing.** You can work with affiliates (influencers, companies, etc) to advertise your game to their followings, and reward them via a custom link (`https://discord.com/activities/<your Activity ID>?custom_id=influencer1`). Then, for every user that starts playing because of said influencer, you can then pay out to the influencer. |
| 18 | +- **Source attribution.** You can use the `custom_id` parameter to figure out how much traffic you’re getting from different marketing sources. |
| 19 | + |
| 20 | +This guide covers implementing a referral link which will feature a reward system for users who share links and those who click them. |
| 21 | + |
| 22 | +#### Implementation Overview |
| 23 | + |
| 24 | +1. Create and track an incentivized link for a promotional campaign, then prompt users to share the link |
| 25 | +2. Handle incoming referrals and grant valid rewards |
| 26 | + |
| 27 | +#### Sharing Links |
| 28 | + |
| 29 | +When implementing sharing, you'll need to: |
| 30 | +1. Generate a unique ID for tracking the promotion |
| 31 | +2. Call the [`shareLink`](/docs/developer-tools/embedded-app-sdk#sharelink) command |
| 32 | +3. Track the share attempt |
| 33 | + |
| 34 | +```javascript |
| 35 | +// Generate a unique ID for this promotion |
| 36 | +// This could be per-campaign, per-user, or per-share depending on your needs |
| 37 | +const customId = await createPromotionalCustomId(); |
| 38 | + |
| 39 | +try { |
| 40 | + const { success } = await discordSdk.commands.shareLink({ |
| 41 | + message: 'Click this link to redeem 5 free coins!', |
| 42 | + custom_id: customId, |
| 43 | + }); |
| 44 | + |
| 45 | + if (success) { |
| 46 | + // Track successful share for analytics/limiting |
| 47 | + await trackSuccessfulShare(customId); |
| 48 | + } |
| 49 | +} catch (error) { |
| 50 | + // Handle share failures appropriately |
| 51 | + console.error('Failed to share link:', error); |
| 52 | +} |
| 53 | +``` |
| 54 | + |
| 55 | +#### Handling Incoming Referrals |
| 56 | + |
| 57 | +When a user clicks a shared link, your activity will launch with referral data available through the SDK: |
| 58 | + |
| 59 | +```javascript |
| 60 | +// Early in your activity's initialization |
| 61 | +async function handleReferral() { |
| 62 | + // Validate the referral data |
| 63 | + if (!discordSdk.customId || !discordSdk.referrerId) { |
| 64 | + return; |
| 65 | + } |
| 66 | + |
| 67 | + try { |
| 68 | + // Verify this is a valid promotion and hasn't expired |
| 69 | + const promotion = await validatePromotion(discordSdk.customId); |
| 70 | + if (!promotion) { |
| 71 | + console.log('Invalid or expired promotion'); |
| 72 | + return; |
| 73 | + } |
| 74 | + |
| 75 | + // Prevent self-referrals |
| 76 | + if (discordSdk.referrerId === currentUserId) { |
| 77 | + console.log('Self-referrals not allowed'); |
| 78 | + return; |
| 79 | + } |
| 80 | + |
| 81 | + // Grant rewards to both users |
| 82 | + await grantRewards({ |
| 83 | + promotionId: discordSdk.customId, |
| 84 | + referrerId: discordSdk.referrerId, |
| 85 | + newUserId: currentUserId |
| 86 | + }); |
| 87 | + } catch (error) { |
| 88 | + console.error('Failed to process referral:', error); |
| 89 | + } |
| 90 | +} |
| 91 | +``` |
| 92 | + |
| 93 | +#### Link Sharing Best Practices |
| 94 | + |
| 95 | +- Generate unique, non-guessable `customId`s |
| 96 | +- Track and validate referrals to prevent abuse |
| 97 | +- Handle edge cases like expired promotions gracefully |
| 98 | +- Consider implementing cool-down periods between shares |
| 99 | +- Do not override the `referrer_id` query parameter directly. When present, `referrer_id` is expected to be a Discord snowflake-type user ID, otherwise it will be set to the message's author id. |
| 100 | + |
| 101 | +--- |
| 102 | + |
| 103 | +## Creating and Managing Custom Incentivized Links |
| 104 | + |
| 105 | +This guide covers creating a customizable [Incentivized Link](/docs/activities/development-guides/growth-and-referrals#prompting-users-to-share-incentivized-links) through the dev portal, and then retrieving the link to be able to share it off-platform. Incentivized Links are used to customize how the embed appears to users. |
| 106 | + |
| 107 | +#### Creating a Link |
| 108 | + |
| 109 | +1. In your Application's portal, visit the Custom Links page under the Activities heading in the navigation pane. |
| 110 | +2. On the Custom Links page, click `Create New` to create a new link. |
| 111 | +3. You will need to upload an image with an aspect ratio of 43:24. |
| 112 | +4. Title, and description are also required. |
| 113 | +5. `custom_id` is an optional field, an explicit `custom_id` query parameter on the link itself will always override the set `custom_id`. |
| 114 | +6. Click Save. |
| 115 | + |
| 116 | +#### Editing a Link |
| 117 | + |
| 118 | +1. Click on a row to open up the modal with all of the data loaded in ready for your edits. |
| 119 | +2. Change the description to something else. |
| 120 | +3. Click Update. |
| 121 | + |
| 122 | +#### Copying a Link |
| 123 | + |
| 124 | +Once you're satisfied with your changes you can click on the copy icon on the row, it'll change colors to green indicating that it copied to your clipboard. You are now able to share this link anywhere. The link will look like: `https://discord.com/activities/<your Activity ID>?link_id=0-123456789`. Even if you've set a `custom_id`, it won't be explicitly included in the link but will be loaded once a user clicks on the link. You can then further shorten this URL if you'd like. |
| 125 | + |
| 126 | +#### Deleting a Link |
| 127 | + |
| 128 | +1. Click on the trash icon on the row of the link you're trying to delete. |
| 129 | +2. You'll have a confirm dialog pop up. |
| 130 | + |
| 131 | +:::warn |
| 132 | +Deleting is irreversible and immediate. Ensure that your link isn't in active use before deleting and/or that your activity gracefully handles any click-throughs from the link. |
| 133 | +::: |
| 134 | + |
| 135 | +#### Best Practices |
| 136 | + |
| 137 | +- Generate unique, non-guessable `customId`s |
| 138 | +- Track and validate referrals to prevent abuse |
| 139 | +- Gracefully handle expirations in your activity for any custom links that are limited time but still live off-platform. |
| 140 | + |
| 141 | +#### User Experience |
| 142 | + |
| 143 | + |
| 144 | + |
| 145 | +Users will see an embed with your information displayed. Clicking "Play" opens the activity and passes through the `custom_id` you've set. A `referrer_id` will be present for links shared on Discord. |
| 146 | + |
| 147 | +--- |
| 148 | + |
| 149 | +## Generating a Custom Link Within Your Activity |
| 150 | + |
| 151 | +This guide covers creating a customizable [Incentivized Link](/docs/activities/development-guides/growth-and-referrals#prompting-users-to-share-incentivized-links) within your activity, and using the `shareLink` API to share the link. |
| 152 | + |
| 153 | +* Allows you to customize the way the link is presented to users via the embed |
| 154 | +* Can be generated on-demand within your activity |
| 155 | +* Ephemeral, 30 day TTL |
| 156 | +* Does not show up in the developer portal |
| 157 | + |
| 158 | +#### Generating a Link |
| 159 | + |
| 160 | +```javascript |
| 161 | +// Convert an image array buffer to base64 string |
| 162 | +const image = base64EncodedImage; |
| 163 | + |
| 164 | +// Generate the quick activity link |
| 165 | +const linkIdResponse = await fetch(`${env.discordAPI}/applications/${env.applicationId}/quick-links/`, { |
| 166 | + method: 'POST', |
| 167 | + headers: { |
| 168 | + Authorization: `Bearer ${accessToken}`, |
| 169 | + }, |
| 170 | + body: { |
| 171 | + custom_id: 'user_123/game_456' |
| 172 | + description: 'I just beat level 10 with a perfect score', |
| 173 | + title: 'Check out my high score!', |
| 174 | + image, |
| 175 | + } |
| 176 | +}); |
| 177 | +const {link_id} = await linkIdResponse.json(); |
| 178 | + |
| 179 | +// Open the Share modal with the generated link |
| 180 | +const {success} = await discordSdk.commands.shareLink({ |
| 181 | + linkId: link_id |
| 182 | +}); |
| 183 | +success ? console.log('User shared link!') : console.log('User did not share link!'); |
| 184 | +``` |
0 commit comments