Steamworks Documentation
Step by Step: Achievements
In Brief
Use achievements to reward players for hitting certain milestones or for interacting with your game in particular ways.
Level of integration
10 minutes and under 10 lines of code. Steamworks SDK integration necessary.

Introduction

Achievements can be used as a way to encourage and reward player interactions and milestones within your game. They are often used for marking number of kills, miles driven, chests opened or other common actions within your game. And they can also be used to help your players discover different ways of playing your game. When unlocked, these achievements will pop up in the corner of the players' window and will be marked within an achievement page for that player.

As your game grows, you can organize its achievements into Achievement Sets. Sets let you group achievements in ways that make sense for your game, add achievements for DLC without affecting completion of the base game, and retire achievements for content that has been removed without taking them away from players who earned them. See Achievement Sets below for details.

Note: Achievement Sets are currently in beta. We'll continue making improvements during the beta, and this documentation will be updated as things change.

Technical Overview

The following is a quick step by step guide to integrating very basic Steam Achievements into your application in under 10 minutes and under 10 lines of code integrated into your code base. The Steamworks SDK comes with a great example application called Spacewar that shows off the full breadth of Steam features and should be your first stop to see all Steam features in action. This tutorial distills the information found in Spacewar and the Stats and Achievements API down to just the necessary information required for Steam Stats to keep things as straightforward as possible. Please note that there is a considerable amount of overlap between stats and achievements, as such if you are integrating both be aware that a lot of calls can be consolidated.

Achievement Sets are configured entirely in Steamworks. They don't require any additional code, and your game unlocks achievements in a set using the same API names and calls described in this guide.

Step 1 - Defining your game's Achievements

Achievements are application specific and are setup on the Achievement Configuration page in the Steamworks App Admin backend. The following is the list of achievements from the Steamworks sample app Spacewar:

spacewar_achievement_examplescreenshot.jpg

Accessing the Achievements Editor

Achievements are created and managed in the achievements editor:
  1. From your app's landing page in Steamworks, select Edit Steamworks Settings.
  2. Select Stats & Achievements > Achievements.
  3. Click the banner at the top of the page to open the new achievements editor.

You need permission to edit the app's info in order to use the achievements editor.

The editor has two tabs:
  • Manage Achievements - Create, edit, and organize your sets and achievements.
  • Bulk Import/Export - Export and import your achievements as CSV files, and upload icons in bulk. See Bulk Import/Export below.

The top of the editor shows how many achievements and sets your game is using out of your limits, and links to preview your achievements on your own achievements page.

Creating and Editing Achievements

All of your achievements belong to the Base game achievements set unless you assign them to another set. To create an achievement, click Create Achievement in the set it should belong to. To edit an achievement, select it in the achievements table.

FieldDescription
API NameA unique name your game passes to the Steamworks API, such as ACH_WIN_ONE_GAME. Required.
Display NameThe name of the achievement shown to players. Localizable.
DescriptionThe description of the achievement shown to players. Localizable.
IconsThe Achieved icon and Unachieved icon. See Icons below.
Set ByWho can unlock the achievement: the client, a game server, or an official game server.
Progress StatOptionally, a stat used to display progress toward this achievement, along with the Stat Range that maps to 0% and 100% progress.
VisibilityVisible, or Spoiler to hide the achievement's details until it's unlocked.
Optional StatusAvailable, or Archived if the achievement can no longer be earned.
In SetThe set this achievement belongs to.

The achievements table also shows each achievement's ID, its set, how it's set, and its global unlock rate. Use the Filter box in the toolbar to find achievements by name, description, or API name.

Deleting an achievement removes it for everyone, including players who have already unlocked it. If an achievement has been earned by players, the editor will recommend archiving it instead. See Archiving below.

Icons

For best results, achievement icons should be 256x256 pixel PNG images. They can be as small as 64x64, but we recommend using the larger size. Icons must be square, and larger icons are scaled down to 256x256. JPG images are also accepted.

We recommend making achieved icons colorful and unachieved icons grayscale. You don't need to create an unachieved icon yourself: click Generate in the achievement editor, or use the Automatically generate unachieved icons option when uploading in bulk, to create a grayscale unachieved icon from the achieved icon. You can replace the generated icon with your own at any time.

Localization

Use the Language selector in the toolbar to view and edit your achievements in each of your game's languages. A warning icon is shown in the toolbar when some languages are missing localized text, and each achievement or set that's missing text is marked in the editor.

To choose which languages your achievements support, click the edit button next to Language in the toolbar, or click Configure Languages on the Bulk Import/Export tab. These languages are used in the editor and in the localization CSV files. When you query achievements through the API, Steam returns the text for the requested language.

Limits

ItemLimit
Achievements per app5,000 (100 for apps that have not yet been vetted)
Sets per app40, including the base game set

Archived achievements count toward the achievement limit.

Step 2 - Encapsulating Achievements work

The following code is game independent and can be added to your game as you see fit. The class is fully functional as is but can be easily extended to meet any further needs. All of this code was taken directly from the Spacewar example files StatsAndAchievements.cpp/h.

Header File

We first define a structure to hold our achievement data received from Steam and provide a macro for creating objects of that type. This data maps directly to what is found on the Achievement Configuration page.
#define _ACH_ID( id, name ) { id, #id, name, "", 0, 0 } struct Achievement_t { int m_eAchievementID; const char *m_pchAchievementID; char m_rgchName[128]; char m_rgchDescription[256]; bool m_bAchieved; int m_iIconImage; };

Next we define a helper class that will wrap all of the Steam Stats API calls as well as creating all of the Steam callbacks.
class CSteamAchievements { private: int64 m_iAppID; // Our current AppID Achievement_t *m_pAchievements; // Achievements data int m_iNumAchievements; // The number of Achievements bool m_bInitialized; // Are we ready to use the API? public: CSteamAchievements(Achievement_t *Achievements, int NumAchievements); ~CSteamAchievements(); bool Initialize(); bool SetAchievement(const char* ID); STEAM_CALLBACK( CSteamAchievements, OnUserStatsStored, UserStatsStored_t, m_CallbackUserStatsStored ); STEAM_CALLBACK( CSteamAchievements, OnAchievementStored, UserAchievementStored_t, m_CallbackAchievementStored ); };

Code File

Constructor

Parameters - The constructor takes a pointer to an array of achievements along with the length of the array. The formating of that array will be covered in the main game code later.
Returns - N/A
What it does - The constructor initializes a number of members along with grabbing the AppID we are currently running as. In addition it hooks up the call back methods to handle asynchronous calls made to Steam. Finally it makes an initial call to Initialize() to check that the API is ready.
CSteamAchievements::CSteamAchievements(Achievement_t *Achievements, int NumAchievements): m_iAppID( 0 ), m_bInitialized( false ), m_CallbackUserStatsStored( this, &CSteamAchievements::OnUserStatsStored ), m_CallbackAchievementStored( this, &CSteamAchievements::OnAchievementStored ) { m_iAppID = SteamUtils()->GetAppID(); m_pAchievements = Achievements; m_iNumAchievements = NumAchievements; m_bInitialized = Initialize(); }

Initialize()

Parameters - None
Returns - a bool representing if the call succeeded or not. If the call failed then most likely Steam is not initialized. Make sure you have a Steam client open when you try to make this call and that SteamAPI_Init has been called before it.
What it does - Ensures that Steam is loaded and there is a User context logged in.
bool CSteamAchievements::Initialize() { // Is Steam loaded? If not we can't get stats. if ( NULL == SteamUserStats() || NULL == SteamUser() ) { return false; } // Is the user logged on? If not we can't access stats. if ( !SteamUser()->BLoggedOn() ) { return false; } return true; }

SetAchievement()

Parameters - The string identifier of the Achievement that you want to set (e.g. "ACH_WIN_ONE_GAME")
Returns - a bool representing if the call succeeded or not. If the call failed then Steam is not initialized.
What it does - This method sets a given achievement to achieved and sends the results to Steam. You can set a given achievement multiple times so you don't need to worry about only setting achievements that aren't already set. This is an asynchronous call which will trigger two callbacks: OnUserStatsStored() and OnAchievementStored().
bool CSteamAchievements::SetAchievement(const char* ID) { // Have we received a call back from Steam yet? if (m_bInitialized) { SteamUserStats()->SetAchievement(ID); return SteamUserStats()->StoreStats(); } // If not then we can't set achievements yet return false; }

OnUserStatsStored()

Parameters - N/A
Returns - Nothing
What it does - This method is a callback that is called anytime you attempt to store stats on Steam.
void CSteamAchievements::OnUserStatsStored( UserStatsStored_t *pCallback ) { // we may get callbacks for other games' stats arriving, ignore them if ( m_iAppID == pCallback->m_nGameID ) { if ( k_EResultOK == pCallback->m_eResult ) { OutputDebugString( "Stored stats for Steam\n" ); } else { char buffer[128]; _snprintf( buffer, 128, "StatsStored - failed, %d\n", pCallback->m_eResult ); OutputDebugString( buffer ); } } }

OnAchievementStored()

Parameters - N/A
Returns - Nothing
What it does - This method is a callback that is called anytime Achievements are successfully stored on Steam.
void CSteamAchievements::OnAchievementStored( UserAchievementStored_t *pCallback ) { // we may get callbacks for other games' stats arriving, ignore them if ( m_iAppID == pCallback->m_nGameID ) { OutputDebugString( "Stored Achievement for Steam\n" ); } }

Step 3 - Integrating into your game

The following is a complete listing of code snippets that you would need to integrate into your game in the appropriate locations.

Defines and Globals

The following is the list of includes that are needed to build with Achievements, an enum of our game specific achievements and a global pointer to our helper object. Please note that the achievements match those of the Admin page on Steamworks.
... #include "steam_api.h" // Defining our achievements enum EAchievements { ACH_WIN_ONE_GAME = 0, ACH_WIN_100_GAMES = 1, ACH_TRAVEL_FAR_ACCUM = 2, ACH_TRAVEL_FAR_SINGLE = 3, }; // Achievement array which will hold data about the achievements and their state Achievement_t g_Achievements[] = { _ACH_ID( ACH_WIN_ONE_GAME, "Winner" ), _ACH_ID( ACH_WIN_100_GAMES, "Champion" ), _ACH_ID( ACH_TRAVEL_FAR_ACCUM, "Interstellar" ), _ACH_ID( ACH_TRAVEL_FAR_SINGLE, "Orbiter" ), }; // Global access to Achievements object CSteamAchievements* g_SteamAchievements = NULL; ...

Initialization

The call to SteamAPI_Init initializes all of Steam and must be called before anything else. If that call succeeds then we create the helper object by passing in the array of achievements along with the size of the array.
... // Initialize Steam bool bRet = SteamAPI_Init(); // Create the SteamAchievements object if Steam was successfully initialized if (bRet) { g_SteamAchievements = new CSteamAchievements(g_Achievements, 4); } ...

Processing Callbacks

To ensure that we process all Steam callbacks we need to regularly pump for new messages. This is achieved by adding this call to the game loop.
... SteamAPI_RunCallbacks(); ...

Triggering Achievements

Triggering an achievement is as simple as a single call passing along the achievement identifier.
... if (g_SteamAchievements) g_SteamAchievements->SetAchievement("ACH_WIN_100_GAMES"); ...

Note: Steam will not unlock an achievement in a DLC set for a player who can't play that DLC, or an achievement in an archived set. Make sure your game only awards DLC achievements to players who own the DLC, and stops awarding achievements once you archive them. See Achievement Sets below.

Shutdown

The call to SteamAPI_Shutdown is probably something you already have in your code. It shuts down Steam and must be called before your application exits. Finally we delete the helper object we created.
... // Shutdown Steam SteamAPI_Shutdown(); // Delete the SteamAchievements object if (g_SteamAchievements) delete g_SteamAchievements; ...

Step 4 - Testing and Troubleshooting


To set or clear stats or an achievement without adding code to your game, you can use the Steam client console. Run with steam.exe -console, then:
  • achievement_clear <appid> <achievement name>
  • reset_all_stats <appid>

Previewing and Publishing

Changes you make in the achievements editor are saved to your app's draft configuration. To make them live, publish your changes from the Publish tab in Edit Steamworks Settings, as with any other Steamworks setting.

Before release, you can preview your achievements on your own Steam achievements page, linked from the top of the editor. Use developer-only sets to test new achievements without showing them to players.

To fully enable achievements and complete your release checklist, you also need to check the Steam Achievements option under Supported Features in your store page's basic info. To pass the release checklist, every achievement must have a name in each of the languages you've configured, and must have an icon.

Achievement Sets

Achievement Sets let you organize your game's achievements into named groups, track player completion per set, and add or retire achievements over time without taking away a player's completion. With Achievement Sets, you can:
  • Group achievements in ways that make sense for your game, such as by mode, character, chapter, or event.
  • Add achievements for DLC that only count toward completion for players who own that DLC.
  • Archive achievements and sets for content that has been retired, without removing them from players who earned them.
  • Build and test achievements in developer-only sets that are hidden from players.
  • Manage achievement definitions, set assignments, icons, and localization in bulk using CSV and image files.

Base Game Set

Every game has a Base game achievements set. Achievements that aren't assigned to another set belong to the base game set, so if you don't create any additional sets, all of your achievements are in the base game set. For most games, this set will contain most of your achievements.

The base game set can't be renamed, deleted, or reordered. It is always shown first, unless it is empty--in which case it won't be displayed (but will still count against the limit).

Custom Sets

You can create additional sets to organize your achievements. Each set has a name, which is shown to players, and an optional restriction:

RestrictionWho can earn achievements in the set
All players of the gameAnyone who can play the game.
Owners of (DLC)Only players who can play the selected DLC.

Players see progress for each set, and completing a set is tracked separately from completing the rest of the game.

DLC Sets

A set restricted to owners of a DLC is a DLC set. DLC sets:
  • Can be explored by all players on the game's achievements page, but only players who can play the DLC can earn them.
  • Do not count toward completion of the base game or any other set.
  • Stay hidden from players until the DLC is released. This lets you configure and test achievements for upcoming DLC ahead of launch.
  • Use the DLC's store artwork and store link on the achievements page. If the DLC doesn't have a published store page, the base game's artwork and store link are used instead, and the editor will warn you about this.
  • Are shown in an achievements panel on the DLC's store page.

The set name will be displayed with a "DLC" prefix, so you don't need to include "DLC" in the name yourself.

Developer-only Sets

A set marked as Developer-only is only visible to developers of the app, whether or not the app has been released. Only developers can unlock achievements in a developer-only set. Developer-only sets are useful for building and testing new achievements before they're ready to ship.

Archiving

Sometimes a game mode is replaced, a seasonal event ends, or an achievement can no longer be earned. Instead of deleting achievements that players have earned, you can archive them.
  • Archived achievements remain visible to players who unlocked them, and can still be featured on their profiles. Players who haven't unlocked an archived achievement won't see it, and it won't count against their completion of the set it belongs to.
  • Archived sets are only visible to players who previously unlocked an achievement in them. No achievements in an archived set can be unlocked. Players who have unlocked achievements in an archived set can still see all of the set's achievements.

Archiving doesn't change your game. When you archive an achievement, make sure your game no longer awards it.

Spoiler Achievements

Achievements previously marked as Hidden are now called Spoiler achievements. To avoid spoiling your game, a spoiler achievement's name and description aren't shown to players until they unlock it or choose to reveal it. Spoiler and archived achievements aren't shown in the achievements panel on your store page.

Completion

Completion is tracked per set:
  • A player completes a set by unlocking every achievement in it that is still available. Archived achievements that the player hasn't unlocked aren't required.
  • Once a player completes a set, it stays completed, even if you add achievements to that set later.
  • DLC sets only count toward a player's completion if they own the DLC.

Players can show off how many games and sets they have completed on their Steam profile. A game qualifies for the Completionist Showcase on their profile when the player has completed any of the game's sets.

Creating a Set

  1. On the Manage Achievements tab, click Create New Set.
  2. Enter a Set name. The name is shown to players.
  3. Under Restrictions, choose All players of the game, or select a DLC to restrict the set to owners of that DLC. The DLC list includes the DLC listed for your game, along with their app IDs.
  4. Optionally, mark the set as Developer-only.
  5. Save the set.

A set with no achievements in it will not appear to anyone.

Editing a Set

Open the set's menu and choose Edit set to change its name, restrictions, developer-only status, or to mark it as Archived.

Each set shows its Visibility in the editor:

VisibilityMeaning
VisiblePlayers can see this set.
Hidden by restrictionsPlayers can't see this set yet, for example because it's developer-only or its DLC hasn't been released.
Will be visible upon publishPlayers will be able to see this set once you publish your changes.

Reordering Sets

Click Reorder Sets in the toolbar, then drag and drop your sets to choose the order players will see them. The base game set can't be moved.

Deleting a Set

Open the set's menu and choose Delete set. You must move or delete all achievements in a set before you can delete it. If you want to retire a set without removing achievements from players who earned them, archive it instead.

Moving Achievements Between Sets

To move a single achievement, change its In Set field. To move many achievements at once, use Bulk Move:
  1. Click Bulk Move in the achievements table header.
  2. Check the achievements you want to move. The number of selected achievements is shown at the bottom of the page.
  3. Choose a destination set, or choose Create New Set... to create one.
  4. Click Move.
For example, you can turn on the Bulk Move mode, use the search box to filter achievements by api name, then click the checkbox in the column headers to select all visible achievements in a group to move. This workflow is relatively simple and can save quite a bit of time.

The editor will warn you before a move that could affect players:
  • Moving achievements from a visible set to a hidden or unreleased set will hide them from players who have already unlocked them.
  • Moving achievements into a set that players have progress in may break completion for those players.

Note: Adding an achievement to a set that has already been released won't break completion for players, but it may not display naturally. Consider adding a new set instead.

Bulk Import/Export

The Bulk Import/Export tab lets you manage your achievements as files: export CSV files, edit them in a spreadsheet tool, and upload them back along with your icons.

Workflow

  1. Click Export Definitions (.csv), Export Localization (.csv), and/or Export Set Localization (.csv) to download your current data.
  2. Edit the files. Header rows include notes in parentheses describing each column, for example spoiler (true or false). These notes are ignored when you upload the file.
  3. Drag your .csv and .png files onto the upload box, or click Select Files.... You can upload multiple files at once.
  4. Review the Uploaded Files list for any errors. Removing a file undoes everything it contributed. To replace a file, correct it and upload it again.
  5. Review the Pending Changes. Nothing is saved until you click Save imported data.

If your game doesn't have any achievements yet, the definitions and localization exports are templates containing a couple of example rows beginning with EXAMPLE_. You can type over them, delete them, or upload the template as-is to see how importing works.

Achievement Definitions CSV

Exported as <appid>-achievements-definitions.csv. Each row defines one achievement.

ColumnDescription
api_nameRequired, unique. The name your game passes to the API.
setidOptional. The ID of an existing set. Leave blank for the base game set.
permissionOne of Client, GameServer, or OfficialGameServer.
spoilertrue or false.
archivedtrue or false.
progress_stat_nameOptional. The name of an existing stat to use for a progress bar. Leave blank for no progress bar.
progress_stat_minA number, no lower than the stat's own minimum. Must be an integer if the stat is an integer stat.
progress_stat_maxA number, greater than progress_stat_min and no higher than the stat's own maximum. Must be an integer if the stat is an integer stat.

When you upload a definitions CSV, achievements are compared to your existing achievements by API name:
  • To Add - Rows that don't match an existing API name are added as new achievements. If you meant to rename an existing achievement's API name, change it in the editor first or the old data will be removed.
  • To Modify - Existing achievements whose values have changed are updated.
  • Unmodified - Existing achievements whose values haven't changed are left alone.
  • Missing from CSV - Existing achievements that aren't in the file are kept, unless you check Delete these achievements. Be thoughtful when removing achievements because you can't simply add achievements back when they have been removed.

Note: Achievement names and descriptions aren't part of the definitions CSV. Use the localization CSV to set them.

Note: A progress stat must already exist and must have the same permission as the achievement. To create new stats, edit your stats first.

Achievement Localization CSV

Exported as <appid>-achievements-localization.csv. Each achievement has two rows: one for its name and one for its description.

ColumnDescription
api_nameRequired. Must match an api_name from the definitions CSV or an existing achievement. API names are case sensitive here.
fieldname or description.
(one column per language)The text for that language, for example english, french, german.

The language columns match the languages configured for your achievements. If you're starting on localization, configure your languages first so the exported CSV includes those language columns.

If you upload a definitions CSV and a localization CSV together, localization for achievements that are missing from the definitions CSV won't be updated.

Set Localization CSV

Exported as <appid>-achievement-sets-localization.csv. Each row contains one set's name.

ColumnDescription
setidRequired. The ID of an existing set.
(one column per language)The set name in that language. english is required.

Sets must be created in the editor before you can localize them here. The base game set can't be renamed.

Icon Files

Name icon files with the achievement's API name followed by _ACHIEVED or _UNACHIEVED, for example LEVEL_20_ACHIEVED.png and LEVEL_20_UNACHIEVED.png. Icons are automatically assigned to the matching achievement.

Check Automatically generate unachieved icons to create grayscale unachieved icons for any achieved icons you upload.

If you upload a definitions CSV along with your icons, icons are only assigned to achievements included in that CSV. To upload icons on their own, upload them without a definitions CSV.

What Players See

Achievements Page

Players see your achievements on the Steam achievements page, in the Steam Client and on the Steam Community website. The achievements page:
  • Shows progress and completion for each set, including DLC sets.
  • Lets players compare their achievements with up to 3 friends.
  • Shows the global unlock rate for each achievement, and highlights rare achievements.
  • Lets players search achievements and filter them by unlock state or set.

You can link players directly to your game's achievements:

URLShows
https://steamcommunity.com/achievements/<appid>Your game's achievements, without a specific player's progress. Available whether or not the player owns the game.

Store Pages

The achievements panel on your store page shows achievements from your game, excluding spoiler and archived achievements. DLC store pages show achievements from that DLC's set.

Profiles

Players can show off the number of games and sets they've completed in their profile's Achievement Showcase, and can feature games in the Completionist Showcase once they've completed any of the game's sets.

Best Practices

  • Add new sets for new content. Adding achievements to a set that players have already completed may appear confusing for players, as the set will be marked completed but will have locked achievements. Creating a new set for new content, such as a DLC, an update, or a new mode, keeps progress clear for players.
  • Archive instead of deleting. If players have earned an achievement, archive it rather than deleting it, so players keep what they earned.
  • Use DLC sets for DLC achievements. This keeps the base game's completion separate, so players who don't own the DLC aren't blocked from completing your game.
  • Keep set names short and descriptive. Set names are shown to players in many places, including in the Steam Client.
  • Localize set names for each language your game supports, using the set localization CSV or the editor.
  • Test with developer-only sets before releasing new achievements to players.

Frequently Asked Questions

Do I need to update my game or the Steamworks SDK to use Achievement Sets?

No. Sets are configured in Steamworks, and your game unlocks achievements using the same API names and calls as before.

What happens to my existing achievements?

They're all in the base game set. If you don't create any other sets, players will see your achievements as a single list on the new achievements page.

Will players lose completion if I add new achievements?

Players who have already completed a set keep that completion. However, adding achievements to a released set means players who hadn't finished it yet have more to do, so we recommend adding new sets for new content.

What's the difference between archiving and deleting an achievement?

Archived achievements stay visible to players who unlocked them, and no longer count against completion for players who didn't. Deleted achievements are removed for everyone.

Can I move an achievement to a different set after it's released?

Yes, but the editor will warn you if the move could hide the achievement from players who earned it, or affect players' completion.

How many sets can I create?

Up to 40, including the base game set.