Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions discord/developers/docs/activities/how-activities-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
title: How Activities Work
description: An introduction to how Activities work on Discord.
---

Activities are web applications that run in an iframe within Discord on desktop, mobile and web. In order to achieve this, we use the [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) protocol to enable secure communication between your application and Discord.

The [Embedded App SDK](https://github.com/discord/embedded-app-sdk) simplifies this process by managing the `postMessage` protocol on your behalf. For details on available commands and their usage, consult the [SDK Reference](/developers/docs/developer-tools/embedded-app-sdk). Our [Sample Projects](/developers/docs/activities/overview#sample-projects) provide practical examples of how to implement these features.

## Designed for Single-Page Apps (SPAs)

This SDK is intended for use by a single-page application. We recognize developers may be using frameworks or approaches that are not an exact fit for single-page applications. We recommend nesting those frameworks inside your Activity's top-level single-page application and passing messages as you see fit. Please refer to the [Nested Messages App](/developers/docs/activities/overview#sample-projects) sample project for guidance on this approach.

## Activity Lifecycle

1. **Initialization:** When your iframe is loaded within Discord, it will include unique query parameters in its URL. These parameters are identifiable by your application using the Discord SDK.
2. **Handshake Process:** Constructing the SDK instance begins a handshake process with the Discord client. Once the connection is established, the iframe receives a `[FRAME, {evt: 'READY', ...}]` message. The `ready()` method of the SDK instance resolves once a successful connection has been established.
3. **Authorization and Authentication:** After receiving the `READY` payload, your application should perform authorization and authentication to acquire necessary permissions (scopes). This step is crucial for utilizing specific features or scopes, such as `rpc.activities.write`.
4. **Interacting with Discord Client:** Post-authentication, your application can subscribe to events and send commands to the Discord client. Note that attempting to use commands or subscribe to events outside your granted scope will result in errors. Adding new scopes may prompt an OAuth modal for user permission re-confirmation.
5. **Disconnection and Errors:** Receiving a `[CLOSE, {message: string, code: number}]` message indicates an error or a need to restart the connection process.
6. **Sending Errors or Close Requests:** To communicate an error or request a close from the Discord client, send `[CLOSE, {message?: string, code: number}]`. A code other than CLOSE_NORMAL will display the message to the user, while CLOSE_NORMAL results in a silent closure.

## Sample Code and Activity Lifecycle Diagram

<Info>
Below is a minimal example of setting up the SDK. Please see our [Sample Projects](/developers/docs/activities/overview#sample-projects) for more complete sample applications.
</Info>


```javascript
import {DiscordSDK} from '@discord/embedded-app-sdk';
const discordSdk = new DiscordSDK(YOUR_OAUTH2_CLIENT_ID);

async function setup() {
// Wait for READY payload from the discord client
await discordSdk.ready();

// Pop open the OAuth permission modal and request for access to scopes listed in scope array below
const {code} = await discordSdk.commands.authorize({
client_id: YOUR_OAUTH2_CLIENT_ID,
response_type: 'code',
state: '',
prompt: 'none',
scope: ['identify'],
});

// Retrieve an access_token from your application's server
const response = await fetch('/api/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
code,
}),
});
const {access_token} = await response.json();

// Authenticate with Discord client (using the access_token)
auth = await discordSdk.commands.authenticate({
access_token,
});
}
```

This diagram illustrates the communication flow between your application and Discord in the sample code above.

![Diagram of how Activities communicate with Discord](/images/activities/embedded-app-flow-diagram.svg)
105 changes: 105 additions & 0 deletions discord/developers/docs/discovery/best-practices.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
sidebar_label: Best Practices
---

# Discovery Best Practices

So you’ve made an app on Discord and are ready to opt in to discovery on the App Directory! Or maybe you have already listed your app but aren’t seeing as much traction to it as you’d like? Whatever stage you’re at, this guide has some tips and tricks from your friendly Discord Staff members to help boost performance of your App Directory Product Page.

<Info>
This guide references settings and information you can set up and modify within your [app's settings](https://discord.com/developers/applications). If you don't have an app yet, you can follow the [Getting Started guide](/developers/docs/quick-start/getting-started).
</Info>

## The Elevator Pitch

### Quickly tell your users what your app does

App descriptions should convey the value of your app and what it does. Make your app descriptions punchy and to the point - letting folks know what your app does in simple terms while also exciting the potential user to add the app and start using it.

<Info>

Be sure to spell check and review your grammar before posting your descriptions. Your app has the potential to be seen by millions of people!

</Info>

There are a few places where you can define different descriptions of your app within your [app's settings](https://discord.com/developers/applications).

#### App General Information Description

On the **General Information** tab, there is a general **Description** field (max of 400 characters) that appears within your bot user's profile. When a new user clicks on your app within Discord, they'll see this description.

![App description on the General Information tab](/images/bp-productpage-app-description.webp)

#### App Summary

On the **App Directory** tab, the **Summary** field is a short description (max of 200 characters) that users will see when you appear within search results on the App Directory.

When writing your app's Summary, think about how to grab the user's attention and quickly convey the value of your app. Consider the following description:

![Poorly-written app Summary on the App Directory tab](/images/bp-productpage-summary-bad.webp)

While this could be true, it doesn’t really tell folks how the app makes servers better or more fun. The best descriptions start with an attention grabbing sentence that describes a problem a user might want to solve:

![Well-written app Summary on the App Directory tab](/images/bp-productpage-summary-good.webp)

#### App Expanded Description

On the **App Directory** tab, there is an **Expanded Description** field near the bottom of the page. This description appears when someone clicks on your app and enters its profile within the App Directory. This is your opportunity to showcase why a user should install your app, and the best functionality your app has to offer. The description also supports formatting via markdown.

When writing your app's Expanded Description, the first thing you do should be to convey the value of the app to users. After the value is clear, continue on with how to get started with your app after it’s installed.

## Show Your Story

### Include as many relevant visuals as possible

#### Show Your App's Functionality

Add images and gifs to your Product Page and give users a better idea of the amazing functionality of your app. You can start by showing off some of the commands you mentioned in your description and how they work in Discord. What are some of your app’s most popular commands? How do existing users generally interact with your app? The answers to these questions make a great starting point for images on your Product Page.

Additionally, new users need to know what to expect when they install the app so great images should showcase your app in action within a Discord server. The more your images display what your app does and how it appears in Discord, the better.

#### Include Your App's Lore

Other images you may want to include are ones related to your app’s lore (if any). For example, say there was a “Hypesquad App,” I would include the Hypesquad badges and what each of them means (I’m personally Hypesquad balance myself).

#### Add a Video

After adding some images, make a quick screen recording to demonstrate your app’s functionality. Videos are awesome but it's definitely helpful to include images as well, especially for folks who may not watch the entire video.

## Find Your Users

### Utilize search to your advantage

Think of up to five words that describe your app and add them as tags (see image below for an example). Consider what categories your app would fit under or keywords users would type into the search bar when looking for apps to add to their servers.

![App tags which help categorize apps and make them more searchable](/images/bp-productpage-tags.webp)

## Support Your Users

### Engage with your users directly

Your app’s support server is a paramount part of your App Product Page. It’s important to ensure your app has a dedicated server and channel for communication between your app’s users and its developers and maintainers.

<Info>

If your support server isn't [discoverable](https://support.discord.com/hc/en-us/articles/360030843331-Enabling-Server-Discovery), be sure to include an invite link in the "links" section of your App Directory Product Page.

</Info>

Some ways you can successfully use your support server includes:

- Encourage users to share feedback or their experience with your app.
- Offer technical support for users of your app.
- Share app updates in your support server and update your App’s Product Page description if it changes the functionality of your app.

For general best practices on how to run a server, check out our [Community page](https://discord.com/community).

## General Housekeeping

### Final checks to make sure you’re ready to go

Before you can click the final “Enable Discovery” button, ensure that your App Directory Product Page complies with the rest of Discord’s Directory eligibility criteria, [app content requirements](https://support-dev.discord.com/hc/en-us/articles/9489299950487-App-Directory-App-Content-Requirements-Policy) and Developer [Terms of Service](https://support-dev.discord.com/hc/en-us/articles/8562894815383) and [Policy](https://support-dev.discord.com/hc/en-us/articles/8563934450327).

For more details about what this information entails, read our [Help Center article on Profile Pages](https://support-dev.discord.com/hc/en-us/articles/6378525413143-App-Directory-App-profile-pages).

Now you're ready to publish your new App Directory profile and watch your app grow! If you haven’t already, join our official [Discord Developers server](https://discord.gg/discord-developers) to receive more information on how to update your apps. Way to go, Discord Developer!
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Implementing One-Time Purchases

One-time purchases enable you to charge your users for premium functionality with in-app items.

- Before you can add one-time purchases to your app, you must [Enable Monetization](/developers/docs/monetization/enabling-monetization) for your app.
- Once you've confirmed eligibility for your app and team, you will be able to set up a [SKU](/developers/docs/resources/sku) (stock-keeping unit) to represent your one-time purchases.

---

## Types of One-Time Purchases

When creating items for one-time purchase, you can choose between durable and consumable items:

- **Durable Items**: A one-time purchase that is permanent and is not subject to either renewal or consumption, such as lifetime access to an app's premium features.
- **Consumable Items**: A one-time, non-renewable purchase that provides access, such as a temporary power-up or boost in a game.

---

## How One-Time Purchases Work

#### For Durable SKUs
- When a user purchases your durable SKU, Discord creates an [Entitlement](/developers/docs/resources/entitlement) for the purchasing user and that specific [SKU](/developers/docs/resources/sku).
- You will receive an `ENTITLEMENT_CREATE` event via the Gateway.
- This entitlement is now available via the `LIST Entitlements` API endpoint.
- This entitlement will be available on `Interaction Payloads` initiated from the entitled user.

#### For Consumable SKUs
- When a user purchases your consumable SKU, Discord creates an [Entitlement](/developers/docs/resources/entitlement) for the purchasing user and that specific SKU.
- You will receive an `ENTITLEMENT_CREATE` event via the Gateway.
- This entitlement is now available via the `LIST Entitlements` API endpoint.
- This entitlement will be available on `Interaction Payloads` initiated from the entitled user or users in a guild (for guild subscriptions).
- Users cannot repurchase this SKU until you consume the entitlement using the [Consume Entitlement API](/developers/docs/resources/entitlement#consume-an-entitlement) endpoint.
- In [Test Mode](/developers/docs/monetization/implementing-one-time-purchases#using-application-test-mode), repeated purchases are permitted without consumption for developer convenience.
- When you receive an `ENTITLEMENT_CREATE` event for a consumable SKU, you should process the item purchase in your app and consume the entitlement as soon as possible.

---

## Working with Entitlements

When a user purchases a one-time purchase SKU, an entitlement is created. [Entitlements](/developers/docs/resources/entitlement) represent the user's access to your consumable or durable item.

Depending on your app's features, you can use a combination of [Gateway events](/developers/docs/events/gateway-events#entitlements), the [Entitlement HTTP API](/developers/docs/resources/entitlement), and [interaction payloads](/developers/docs/interactions/receiving-and-responding) to keep track of entitlements to users who have purchased items in your app.

### Accessing Entitlements with Gateway Events

When a user purchases a SKU, Discord will emit an [`ENTITLEMENT_CREATE`](/developers/docs/events/gateway-events#entitlements) event. This event will contain the entitlement object that represents the user's access to the SKU. You can use this event to keep track of the user's entitlements in near-time. For One-Time Purchases, you may also receive an `ENTITLEMENT_DELETE` event if the user's entitlement is revoked.

### Accessing Entitlements with the HTTP API

Entitlements are available via the [List Entitlements](/developers/docs/resources/entitlement#list-entitlements) endpoint. You can filter entitlements by a specific user or set of SKUs by using the `?user_id=XYZ` or `?sku_ids=XYZ` query parameters.

### Accessing Entitlements on Interaction Payloads

Entitlements are also available on the `Interaction Payload` when a user interacts with your app. You can find the entitlements on the `entitlements` field of the `Interaction Payload` when [receiving and responding to interactions](/developers/docs/interactions/receiving-and-responding).

### Accessing Entitlements with the Embedded App SDK

When using the [Embedded App SDK](/developers/docs/developer-tools/embedded-app-sdk) to build an [Activity](/developers/docs/activities/overview), you can also [access a user's entitlements](/developers/docs/developer-tools/embedded-app-sdk#getentitlements). Check out the [Implementing In-App Purchases for Activities](/developers/docs/monetization/implementing-iap-for-activities) guide to learn more about monetization with the Embedded App SDK.

Depending on your app's needs, you can use a combination of these methods to keep track of user entitlements.

---

## One-Time Purchase Considerations

When implementing one-time purchases, you should consider the following:

### For Durable One-Time Purchases

When offering durable items, users will have access to the SKU indefinitely. Durable items can't be consumed, so you don't need to worry about the user losing access to the item except in the case of a refund.

### For Consumable One-Time Purchases
When offering consumable items, users can only have one unconsumed entitlement at a time. To handle consumable items in your app or game, you should process and store the consumable item in your app and then make a call to the [Consume Entitlement](/developers/docs/resources/entitlement#consume-an-entitlement) endpoint so that the user can purchase more of this item in the future.

Consuming the entitlement will update the entitlement to return a true value in the entitlement's `consumed` field. You will need to think through how your app keeps track of consumable items to decide on the best strategy for when to consume these entitlements and store the state of the consumable item and quantity in your app.

---

## Prompting Users to Purchase an Item

### Responding with a Premium Button

[Responding with a premium button](/developers/docs/monetization/managing-skus#responding-with-a-premium-button) gives you the ability to prompt users to subscribe to your app when they attempt to use a premium feature without a subscription.

You can do this by sending a message with a [button](/developers/docs/components/reference#button) with a [premium style](/developers/docs/components/reference#button-button-styles) and a `sku_id` that allows the user to upgrade to your premium offering.

### Starting a Purchase from an Activity

If you are using the [Embedded App SDK](/developers/docs/developer-tools/embedded-app-sdk) to build an [Activity](/developers/docs/activities/overview), you can also launch the purchase flow for a specific SKU using the SDK. Check out the [Implementing In-App Purchases for Activities](/developers/docs/monetization/implementing-iap-for-activities) guide to learn more about monetization with the Embedded App SDK.

---

## Testing Your One-Time Purchase Implementation

<Warning>

The method of testing purchases for One-Time Purchases differs from the method for App Subscriptions. **Do NOT use Test Entitlements for One-Time Purchases.**

</Warning>

### Using Application Test Mode

While in Application Test Mode, you can freely make "purchases" of One-Time Purchase SKUs tied to your application. That means you can test buying your consumable and durable items by going through the In-App Purchase flow without any credit card charges.

<Info>

You still need to have a valid payment method on file to "purchase" SKUs in Application Test Mode. It just won't be charged at checkout.

</Info>

To enable it, first, make sure you have a payment method on file in `User Settings -> Billing` and then:

1. Open up the Discord app
2. Click on the Settings cog in the bottom left corner
3. Go to the `Advanced` page under App Settings
4. Toggle "Developer Mode" **on** and "Application Test Mode" **on**, and enter your application ID. You can leave the other settings as-is.
5. Exit user settings

Once you enabled Application Test Mode successfully, you should see an orange bar across the top of your screen with the name of your app.

You can now navigate to your Store page and purchase your one-time purchase items without being charged.

The entitlements tied to items purchased in Application Test Mode can be identified by entitlements with a `type` value of 4 to represent `TEST_MODE_PURCHASE`.

<Warning>

The "Go To SKU" button does not currently work. To purchase your SKU in test mode, go to your Store page.

</Warning>

Loading
Loading