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:

Game Pass Handler Script
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)
end
💡 Tip — Always wrap MarketplaceService calls in pcall(). 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:

Developer Product Server Handler
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 = onProcessReceipt

Now place this in StarterPlayer → StarterCharacterScripts or StarterPlayer → StarterPlayerScripts to let players buy:

Developer Product Purchase Prompt (Client)
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()
💡 Tip — Keep the product ID constant at the top of your script in ALL CAPS. This makes it easy to swap IDs later or add more products without searching through code.

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:

Shop Button Handler
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")
💡 Tip — Use 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.