Roblox in-game shop interface displaying purchasable items and game passes

How to Add a Shop System to Your Roblox Game

A well-designed shop system is how Roblox games generate revenue. Whether you sell game passes for permanent perks, developer products for consumable items, or in-game currency purchases, the shop needs to be reliable, secure, and appealing. This guide covers the full implementation — MarketplaceService integration, receipt processing, shop UI design, and the common pitfalls that cause lost purchases or exploitable transactions.

Game Passes vs. Developer Products

Roblox offers two monetization primitives. Game passes are one-time purchases that grant permanent perks — VIP access, double XP, exclusive cosmetics, extra inventory slots. A player buys a game pass once and owns it forever. Developer products are repeatable purchases for consumable items — 100 coins, a revive token, a temporary speed boost. A player can buy the same developer product unlimited times. Your shop will likely use both. Use MarketplaceService:UserOwnsGamePassAsync(userId, passId) on the server to check game pass ownership. For developer products, use MarketplaceService.ProcessReceipt to handle each purchase. Choose carefully which items should be one-time (passes) versus repeatable (products) — making a powerful item a developer product instead of a game pass means players can buy unlimited power, which can break game balance.

Server-Side Receipt Processing

Receipt processing is the most critical part of your shop system. When a player buys a developer product, Roblox calls your MarketplaceService.ProcessReceipt callback on the server. This callback receives a receiptInfo table containing the player's UserId, the ProductId, and a unique PurchaseId. Your callback must grant the item, save the purchase to the player's data, and return Enum.ProductPurchaseDecision.PurchaseGranted. If you return anything else (or the callback errors), Roblox will retry the callback later — this is how the system handles server crashes during purchases. The critical rule: always save the PurchaseId to the player's DataStore and check for it at the start of ProcessReceipt. If the PurchaseId already exists, the item was already granted and you should return PurchaseGranted without granting again. This prevents duplicate item grants on retries.

  • Always set ProcessReceipt in a server Script, never a LocalScript
  • Save PurchaseId to the player's DataStore before returning PurchaseGranted
  • Check for existing PurchaseId at callback start to prevent duplicate grants
  • Wrap the callback in pcall — an unhandled error means Roblox retries indefinitely
  • Log every transaction with UserId, ProductId, and PurchaseId for debugging

Designing the Shop UI

The shop UI should be clean, scannable, and make purchasing frictionless. Use a grid or list layout with clear item cards. Each card needs: an item image or icon, the item name, a brief description of what it does, and the price with a prominent "Buy" button. Group items by category (Passes, Currency, Consumables, Cosmetics) with tab navigation. Show ownership state — if the player already owns a game pass, change the button to "Owned" and disable it. For developer products, show the player's current quantity (e.g., "You have 340 coins"). Display Robux prices using MarketplaceService:GetProductInfo() so they stay in sync if you change prices on the website. Use UIListLayout with padding and UISizeConstraint for responsive layouts that work on mobile screens.

  • Grid layout with 2-3 columns on desktop, 1 column on mobile
  • Item cards: icon (left), name + description (center), price + buy button (right)
  • Category tabs at the top: Passes, Currency, Boosts, Cosmetics
  • Owned state: green checkmark, "Owned" label, disabled button for purchased passes
  • Confirmation dialog before purchase to prevent accidental buys

Prompting Purchases and Handling Callbacks

When the player clicks "Buy," call MarketplaceService:PromptGamePassPurchase(player, passId) for game passes or MarketplaceService:PromptProductPurchase(player, productId) for developer products. These open Roblox's native purchase dialog. Listen for the result on the client with MarketplaceService.PromptGamePassPurchaseFinished and PromptProductPurchaseFinished signals. Update the UI immediately when a purchase succeeds — change the button to "Owned," update currency display, or play a celebration effect. The actual item grant happens server-side through ProcessReceipt (for products) or by checking UserOwnsGamePassAsync (for passes). Never grant items on the client based on the purchase prompt result — always validate server-side.

In-Game Currency Systems

Many games sell a premium currency (gems, crystals, tokens) via developer products, then let players spend that currency on in-game items. This adds a layer between real money and items, letting you price items flexibly without creating new developer products for each one. Implement currency as a value in the player's save data, managed entirely on the server. The shop UI reads the currency balance via a RemoteFunction, and purchase requests go through a RemoteEvent that the server validates (does the player have enough currency, is the item valid, is the price correct). Never store item prices on the client — an exploiter could modify client-side prices to buy items for free. KitsBlox UI kits include shop templates with currency display, purchase flow, and inventory integration already built.

Testing Purchases in Studio

You cannot test real Robux transactions in Studio, but you can test the flow. MarketplaceService works in Studio's test modes — purchase prompts will appear and you can simulate accepting or declining. Use Studio's Team Test mode to test multiplayer purchase scenarios. For ProcessReceipt testing, manually fire the callback with mock receiptInfo tables. Log every step of the purchase flow (prompt sent, prompt result, receipt received, item granted, data saved) so you can trace issues in production. Before publishing, test edge cases: what happens if the player disconnects during a purchase? What if the DataStore save fails? What if ProcessReceipt is called twice with the same PurchaseId?

Frequently Asked Questions

How do I create a game pass in Roblox?

Go to the Creator Hub, select your game, navigate to Monetization > Passes, and click Create Pass. Upload an icon, set a name and description, configure the Robux price, and publish. Use the resulting pass ID in MarketplaceService:PromptGamePassPurchase() to sell it in your game.

What is ProcessReceipt and why is it important?

ProcessReceipt is a callback on MarketplaceService that Roblox calls on your server when a player buys a developer product. You must grant the item, save the transaction, and return PurchaseGranted. If your callback fails or the server crashes, Roblox retries it automatically. Always save the PurchaseId to prevent duplicate grants on retry.

How do I prevent shop exploits in Roblox?

Run all purchase validation on the server. Never trust client-reported currency balances, item prices, or ownership status. Store prices in a server-side table and compare against the client request. Log every transaction for auditing. Use PurchaseId deduplication to prevent double-grants.

Can I test Roblox purchases without spending Robux?

Yes. Studio's Play and Team Test modes simulate the MarketplaceService purchase flow without real transactions. Purchase prompts appear and you can accept or decline them. For thorough testing, manually call your ProcessReceipt handler with mock data to test edge cases like duplicate receipts and failed saves.

Looking for assets? Browse the library →