Monetizing your game is one of the biggest reasons developers create on Roblox. Game Passes and Developer Products let you earn Robux directly from players. Game Passes are one-time permanent purchases (like a VIP badge), while Developer Products are consumable items players can buy repeatedly (like game currency or power-ups).
Both require setup in the Creator Dashboard before you can sell them in your game. Once created, you'll use scripts to detect purchases and reward players.
Create Game Passes
Game Passes are permanent cosmetic or functional upgrades. A player buys once, owns forever.
First, go to the Creator Dashboard at create.roblox.com. Select your game and navigate to Monetization > Game Passes. Click Create a Game Pass.
You'll set:
- Name: What players see in the shop (e.g., "VIP Pass")
- Description: Explain what it gives them
- Price: In Robux (minimum 10 Robux)
- Icon: A 512×512 PNG or JPG image
After publishing, copy the Game Pass ID from the dashboard. You'll need this number in your scripts.
Create Developer Products
Developer Products are items players buy repeatedly. Use them for currency, power-ups, or cosmetics that reset.
In the Creator Dashboard, go to Monetization > Developer Products. Click Create a Developer Product.
Configure:
- Name: Product name (e.g., "1000 Coins")
- Description: What it does
- Price: In Robux (minimum 5 Robux)
- Icon: 512×512 image
Save and copy the Product ID—you'll use this in scripts just like Game Pass IDs.
Handle Game Pass Purchases in Scripts
You'll use the MarketplaceService to check if a player owns a Game Pass and trigger rewards.
Place this script in ServerScriptService:
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
-- Replace with your actual Game Pass ID
local VIP_PASS_ID = 12345678
local function onPlayerAdded(player)
local hasPass = false
-- Check if player owns the Game Pass
local success, message = pcall(function()
hasPass = MarketplaceService:UserOwnsGamePassAsync(player.UserId, VIP_PASS_ID)
end)
if success then
if hasPass then
-- Give the player VIP benefits
print(player.Name .. " owns the VIP Pass!")
-- Add your reward logic here (e.g., give extra coins, unlock features)
end
else
warn("Error checking Game Pass:", message)
end
end
Players.PlayerAdded:Connect(onPlayerAdded)
-- Also check existing players when script starts
for _, player in pairs(Players:GetPlayers()) do
onPlayerAdded(player)
endpcall(). If players have bad connections, the check might fail. pcall() catches errors without crashing your server.Why this works: UserOwnsGamePassAsync() checks the Roblox servers to see if a player's account has purchased the pass. The pcall() wraps it safely. When a new player joins, you check immediately. For players already in the game when the script loads, you loop through Players:GetPlayers() to check them too.
Handle Developer Product Purchases
Developer Products use a different flow. You prompt the purchase, then listen for the result.
First, place this in ServerScriptService to receive purchase confirmations:
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
-- Replace with your Developer Product ID
local COINS_PRODUCT_ID = 87654321
local function onProcessReceipt(receiptInfo)
local player = Players:GetPlayerByUserId(receiptInfo.UserId)
if not player then
-- Player left; return Pending to retry later
return Enum.ProductPurchaseDecision.NotProcessed
end
local productId = receiptInfo.ProductId
if productId == COINS_PRODUCT_ID then
-- Player bought coins! Give them to the player
print(player.Name .. " bought coins!")
-- Add your reward logic here
-- Example: player.leaderstats.Coins.Value = player.leaderstats.Coins.Value + 1000
-- Tell Roblox we processed it (prevents double-buying)
return Enum.ProductPurchaseDecision.PurchaseGranted
end
-- Unknown product
return Enum.ProductPurchaseDecision.NotProcessed
end
MarketplaceService.ProcessReceipt = onProcessReceiptNow place this in StarterPlayer → StarterCharacterScripts or StarterPlayer → StarterPlayerScripts to let players buy:
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local COINS_PRODUCT_ID = 87654321
-- Function to prompt purchase
local function buyCoins()
MarketplaceService:PromptProductPurchase(player, COINS_PRODUCT_ID)
end
-- Call this when the player clicks a "Buy Coins" button
-- For example:
-- buyCoins()Why this works: On the client (player's device), PromptProductPurchase() opens the purchase UI. After they buy or cancel, the server's ProcessReceipt function fires. Returning PurchaseGranted tells Roblox the purchase was successful. If you return NotProcessed, Roblox will try again later—useful if the player left mid-transaction.
Connect Purchases to Buttons
Most games sell passes and products via a GUI shop. Here's a simple example:
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
-- Assume you have a ScreenGui with buttons named "BuyVIPButton" and "BuyCoinsButton"
local shopGui = playerGui:WaitForChild("ShopGui")
local buyVipButton = shopGui:WaitForChild("BuyVIPButton")
local buyCoinsButton = shopGui:WaitForChild("BuyCoinsButton")
local VIP_PASS_ID = 12345678
local COINS_PRODUCT_ID = 87654321
buyVipButton.MouseButton1Click:Connect(function()
MarketplaceService:PromptGamePassPurchase(player, VIP_PASS_ID)
end)
buyCoinsButton.MouseButton1Click:Connect(function()
MarketplaceService:PromptProductPurchase(player, COINS_PRODUCT_ID)
end)Place this script in StarterPlayer → StarterPlayerScripts. It waits for your GUI buttons, then opens the purchase prompt when clicked.
Test Your Purchases
You can test in Studio before publishing to live players.
In Roblox Studio, click Test > Play. Run the game and trigger your purchase code. You should see the purchase prompt appear. It won't charge you in Studio, but you'll confirm the flow works.
Always test:
- The prompt opens when you click the button
- The prompt closes if you cancel
- Server-side rewards trigger after purchase (check the Output window for your
print()messages) - Purchasing the same item twice works for Developer Products
- Game Passes prevent duplicate purchases (trying to buy twice shows "Already owned")
print() and warn() statements throughout to debug. Check the Output window (View → Output) to see what's happening.Best Practices
Always use pcall(): MarketplaceService calls can fail if the player loses connection. Wrap them in pcall() to avoid crashing your server.
Store IDs in variables: Don't hardcode product IDs scattered throughout your code. Define them once at the top of your script.
Separate client and server: Purchase prompts go on the client (StarterPlayer scripts). Receipt handling goes on the server (ServerScriptService). Never trust the client to award rewards.
Use configuration modules: For games with many products, create a ModuleScript that lists all IDs and rewards. This keeps your code organized as your game grows.
Check ownership on spawn: When a player joins or respawns, check their Game Pass status and re-apply benefits. This handles server restarts where data might reset.
Monetization Tips
Pricing matters. Prices between 10–100 Robux sell well. Game Passes for cosmetics or convenience (like no ads) work better than p2w features—players resent pay-to-win.
Test your rewards. If a VIP Pass gives 2x coins, make sure it actually gives 2x. Broken purchases destroy trust fast.
Be transparent. Tell players what they're buying before the prompt. "Buy VIP for 50 Robux to get 2x coins" is better than a mysterious button.