Skip to content

Commit 976b4a7

Browse files
authored
Split activities development guides into separate pages (#7496)
1 parent f1545b4 commit 976b4a7

18 files changed

+1176
-1120
lines changed

docs/activities/building-an-activity.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ Back in your app's settings, click on the **URL Mappings** page under **Activiti
316316
|--------|-----------------------------------------|
317317
| `/` | `funky-jogging-bunny.trycloudflare.com` |
318318
319-
Read details about URL Mapping [in the development guide](/docs/activities/development-guides#url-mapping).
319+
Read details about URL Mapping [in the development guide](/docs/activities/development-guides/local-development#url-mapping).
320320
321321
### Enable Activities
322322
@@ -330,7 +330,7 @@ Find the first checkbox, labeled `Enable Activities`. Turn it on 🎉
330330
331331
When you enable Activities for your app, a [default Entry Point command](/docs/interactions/application-commands#default-entry-point-command) called "Launch" is automatically created. This [Entry Point command](/docs/interactions/application-commands#entry-point-commands) is the primary way for users to launch your Activity in Discord.
332332
333-
By default, interactions with this command will result in Discord opening your Activity for the user and posting a message in the channel where it was launched from. However, if you prefer to handle the interactions in your app, you can update the [`handler` field](/docs/interactions/application-commands#entry-point-handlers) or create your own. Additional details are in the Entry Point command [documentation](/docs/interactions/application-commands#entry-point-commands) and [development guide](/docs/activities/development-guides#setting-up-an-entry-point-command).
333+
By default, interactions with this command will result in Discord opening your Activity for the user and posting a message in the channel where it was launched from. However, if you prefer to handle the interactions in your app, you can update the [`handler` field](/docs/interactions/application-commands#entry-point-handlers) or create your own. Additional details are in the Entry Point command [documentation](/docs/interactions/application-commands#entry-point-commands) and [development guide](/docs/activities/development-guides/user-actions#setting-up-an-entry-point-command).
334334
335335
336336
### Running your Activity in Discord
@@ -346,7 +346,7 @@ Clicking on your app will launch your locally running app from inside Discord!
346346
:::info
347347
**Customizing your Activity**
348348
349-
If you'd like to set images for your Activity, you can learn how to do that [here](/docs/activities/development-guides#setting-up-activity-metadata).
349+
If you'd like to set images for your Activity, you can learn how to do that [here](/docs/activities/development-guides/assets-and-metadata#setting-up-activity-metadata).
350350
:::
351351
352352
We're looking pretty good so far, but we haven't wired up any Discord functionality yet. Let's do that next.
@@ -461,7 +461,7 @@ Before we call your backend activity server, we need to be aware of the Discord
461461
For this tutorial, we are going to prefix the API call to `/api/token/` with `/.proxy`, but you can also use the SDK's `patchUrlMappings()` method to automatically prefix calls to your external resources for the proxy.
462462
:::
463463
464-
Learn more about this topic in the guides for [Constructing a Full URL](/docs/activities/development-guides#construct-a-full-url) and [Using External Resources](/docs/activities/development-guides#using-external-resources).
464+
Learn more about this topic in the guides for [Constructing a Full URL](/docs/activities/development-guides/networking#construct-a-full-url) and [Using External Resources](/docs/activities/development-guides/networking#using-external-resources).
465465
466466
### Calling your backend server from your client
467467
@@ -515,7 +515,7 @@ async function setupDiscordSdk() {
515515
// Retrieve an access_token from your activity's server
516516
// Note: We need to prefix our backend `/api/token` route with `/.proxy` to stay compliant with the CSP.
517517
// Read more about constructing a full URL and using external resources at
518-
// https://discord.com/developers/docs/activities/development-guides#construct-a-full-url
518+
// https://discord.com/developers/docs/activities/development-guides/networking#construct-a-full-url
519519
const response = await fetch("/.proxy/api/token", {
520520
method: "POST",
521521
headers: {

docs/activities/development-guides.mdx

Lines changed: 44 additions & 1092 deletions
Large diffs are not rendered by default.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
sidebar_label: Assets and Metadata
3+
---
4+
5+
[Home](/docs/intro) > [Activities](/docs/activities/overview) > [Development Guides](/docs/activities/development-guides) > {sidebar_label}
6+
7+
# Assets and Metadata
8+
9+
## Setting Up Activity Metadata
10+
11+
The Activity Shelf is where users can see what Activities can be played. It has various metadata and art assets that can be configured.
12+
13+
To update your app's metadata in the Discord Developer Portal, navigate to the `Settings -> General Information` tab of your app.
14+
15+
- **Application Name:** The publicly visible name of your app.
16+
- **Application Icon:** The publicly visible icon for your app.
17+
- **Application Description:** The application description is shown in the view of the Activity Shelf Item.
18+
- **Max Participants:** The max participants indicate the maximum number of players for your application.
19+
- Max Participants is displayed above the name in the 1-up view: `Up to X participants`.
20+
- Leaving this field empty defaults to `Unlimited participants`.
21+
- Max Participants is also displayed under the name in the 2-up view.
22+
23+
:::info
24+
An app can have a different application name and avatar from the application's bot username and avatar. Both sets of metadata are public-facing and may be visible in various situations when a user interacts with your app. You can view your bot's username on the `Settings -> Bot` tab.
25+
:::
26+
27+
---
28+
29+
## Setting Up Activity Art Assets
30+
31+
The Activity Shelf is where users can see what Activities can be played. It has various metadata and art assets that can be configured.
32+
33+
To update your app's embedded-specific art assets in the Discord Developer Portal, navigate to the `Activities -> Art Assets` tab of your app.
34+
35+
## Embedded Background
36+
37+
Used as a background overlay in Grid view. Artwork should be clustered around the edges of the image leaving space in the center of the image so the UI does not clash with it.
38+
39+
#### Specifications
40+
- 16:9 aspect ratio
41+
- At least 1024 pixels wide
42+
43+
## Cover Art
44+
45+
Used as the main image in the Activity Shelf. It is suggested that this image contain the title and some art in the background.
46+
47+
#### Specifications:
48+
- Image can be displayed at both 16:9 and 13:11 aspect ratios
49+
- At least 1024 pixels wide
50+
51+
52+
## App Tile
53+
54+
There are two views of an application tile. The regular size tile (2-up tile) and the larger "featured" application tile (1-up tile).
55+
56+
## Video Preview
57+
58+
Hovering over the cover image should start playing a preview video of the Application. The preview videos should be no more than 10 seconds long. If no video is provided, nothing will happen as you hover over the application.
59+
60+
#### Specifications: 640 x 360, mp4 format, under 10 seconds long, under 1 MB in size
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
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+
![custom-link-embed](images/activities/custom-link-embed.png)
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+
```
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
sidebar_label: Layout
3+
---
4+
5+
[Home](/docs/intro) > [Activities](/docs/activities/overview) > [Development Guides](/docs/activities/development-guides) > {sidebar_label}
6+
7+
# Layout
8+
9+
## Application Orientation
10+
11+
#### Locking Application Orientation
12+
13+
This SDK provides APIs for locking the application to specific orientations. The possible lock states are `UNLOCKED`, `PORTRAIT`, and `LANDSCAPE`. `lock_state` is the default lock state, and it affects the app orientation when the application is focused. `picture_in_picture_lock_state` determines the PIP aspect ratio, and `grid_lock_state` determines the grid tile aspect ratio for the application. When `picture_in_picture_lock_state` is not set, the application PIP falls back to `lock_state` to determine the aspect ratio. When `grid_lock_state` is not set, the application grid tile falls back to `picture_in_picture_lock_state` to determine its aspect ratio, and if `picture_in_picture_lock_state`is not set, it uses `lock_state`.
14+
15+
Calling `setOrientationLockState` with an `undefined` or omitted value for `picture_in_picture_lock_state` or `grid_lock_state` will not change the corresponding lock states for the application. Calling `setOrientationLockState` with a null value for `picture_in_picture_lock_state` or `grid_lock_state` will clear the application's corresponding lock states such that those layout modes will use the fallback lock states.
16+
17+
```javascript
18+
import {DiscordSDK, Common} from '@discord/embedded-app-sdk';
19+
const discordSdk = new DiscordSDK(clientId);
20+
await discordSdk.ready();
21+
22+
// Set a default lock state
23+
discordSdk.commands.setOrientationLockState({lock_state: Common.OrientationLockStateTypeObject.LANDSCAPE});
24+
25+
// or set both a default lock state and a picture-in-picture lock state
26+
discordSdk.commands.setOrientationLockState({
27+
lock_state: Common.OrientationLockStateTypeObject.PORTRAIT,
28+
picture_in_picture_lock_state: Common.OrientationLockStateTypeObject.LANDSCAPE,
29+
grid_lock_state: Common.OrientationLockStateTypeObject.LANDSCAPE,
30+
});
31+
```
32+
33+
#### Configuring Default Orientation Lock State Through the Developer Portal
34+
35+
It's also possible to configure an application with a default orientation lock state via the Developer Portal. Using this method, the Discord app will apply the orientation lock when launching the application before the SDK has been initialized. This can create a smoother application launch flow where the application starts in the correct orientation rather than switching to the correct orientation after some delay after the application requests an orientation lock via the SDK. The Developer Portal supports setting a different default orientation lock states for phones versus tablets.
36+
37+
![default-orientation-lock-state](images/activities/default_orientation_lock_state.png)
38+
39+
#### Subscribing to Screen Orientation Updates
40+
41+
To listen to the screen orientation (which is sometimes different from the physical device orientation), subscribe to the `ORIENTATION_UPDATE` event. Discord will publish the current orientation upon event subscription, and it'll also publish any orientation changes that happen afterward.
42+
43+
```javascript
44+
const handleOrientationUpdate = (update: {screen_orientation: number}) => {
45+
switch (update.screen_orientation) {
46+
case Common.OrientationTypeObject.PORTRAIT:
47+
...
48+
case Common.OrientationTypeObject.LANDSCAPE:
49+
...
50+
default:
51+
...
52+
}
53+
}
54+
55+
discordSdk.subscribe('ORIENTATION_UPDATE', handleOrientationUpdate);
56+
```
57+
58+
---
59+
60+
## Application Layout Mode
61+
62+
There are three layout modes that an application can be in: focused, picture-in-picture (PIP), or grid mode. Activities can subscribe to the layout mode to determine when to optionally change their layouts to optimize for each layout mode. Old Discord clients only support the `ACTIVITY_PIP_MODE_UPDATE` event, while new Discord clients support both `ACTIVITY_PIP_MODE_UPDATE` and `ACTIVITY_LAYOUT_MODE_UPDATE`. Use `subscribeToLayoutModeUpdatesCompat` and `unsubscribeFromLayoutModeUpdatesCompat` to subscribe to both events with backward compatibility for old Discord clients that only support `ACTIVITY_PIP_MODE_UPDATE`. Here's an example using React:
63+
64+
```javascript
65+
export default function LayoutMode() {
66+
const handleLayoutModeUpdate = React.useCallback((update: {layout_mode: number}) => {
67+
...
68+
}, []);
69+
70+
React.useEffect(() => {
71+
discordSdk.subscribeToLayoutModeUpdatesCompat(handleLayoutModeUpdate);
72+
return () => {
73+
discordSdk.unsubscribeFromLayoutModeUpdatesCompat(handleLayoutModeUpdate);
74+
};
75+
}, [handleLayoutModeUpdate]);
76+
}
77+
```

0 commit comments

Comments
 (0)