Shop extension (Cash Pack Shop → DevProducts Handler)
A worked example of a shop / monetization extension: a package that adds purchasable products and a shop section to the DevProducts Handler base. Here it's Cash Pack Shop. Read the Extensions overview first for the shared contract.
The DevProducts Handler calls these "Connected Shop Libraries" — each registers its own section against a shared
Shopdispatch layer, so multiple shop extensions coexist in one place without editing each other.
What it extends
The DevProducts Handler exposes three extension points that are all auto-discovered:
SharedSource/Datas/Monetization/DevProductSets/— product data filesClientSource/…/ProductController/…/Shop/Sections/— shop UI section filesServerScriptService/…/ProductService/…/DevProductHandler/— server grant logic
A shop extension drops one file into each.
Step 1 — Declare the base systems
Three required dependencies — the handler, the currency it grants, and the shop UI it slots into:
[
{
"display_name": "DevProducts Handler",
"unique_id": "829a1885-182d-4c0a-8ee4-f9f3650ebd26",
"always_on": true,
"isInitiallyChecked": true
},
{
"display_name": "Currency System",
"unique_id": "d482364f-a580-4594-a74e-5b43c9b51124",
"always_on": true,
"isInitiallyChecked": true
},
{
"display_name": "Robux Shop",
"unique_id": "428973bf-60c3-4e7b-b7b4-d1cab475294a",
"always_on": true,
"isInitiallyChecked": true
}
]This is the key lesson for shop extensions: list every system you depend on, not just the handler. Cash Pack needs the Currency System to grant cash and the Robux Shop for its section to appear in.
The zip
Cash_Pack_Shop/
├─ Instructions.md
├─ metadata.json # name, description, version, created_by
├─ relevant_systems.json # [ DevProducts Handler, Currency System, Robux Shop ] all always_on
├─ Unpack_On_Source/
│ ├─ ReplicatedStorage/ClientSource/Client/ProductController/Components/Others/
│ │ Shop/Sections/CashSection.lua # registers a shop section (drop-in)
│ ├─ ReplicatedStorage/SharedSource/Datas/Monetization/
│ │ DevProductSets/CashProducts.lua # dev product data (drop-in)
│ └─ ServerScriptService/ServerSource/Server/ProductService/Components/Others/
│ DevProductHandler/CashHandler.lua # server grant logic (drop-in)
└─ To_Upload_By_User/
└─ DevProducts/superbullet_metadata.json # maps tokens → user's dev product IDsNo Unpack_On_Roblox_Studio/ here — the shop UI is built by the section script against the existing shop window.
Step 2 — Drop-in files
Each file has a unique name (Cash…) and lands in an extension-point folder the base already scans:
-- Unpack_On_Source/ReplicatedStorage/SharedSource/Datas/Monetization/DevProductSets/CashProducts.lua
return {
{ Name = "Cash1", Description = "Adds 2,500 cash", ProductId = 3485188014 },
{ Name = "Cash2", Description = "Adds 25,000 cash", ProductId = 3485188012 },
{ Name = "Cash3", Description = "Adds 100,000 cash", ProductId = 3485188013 },
{ Name = "Cash4", Description = "Adds 500,000 cash", ProductId = 3485188010 },
}CashSection.luaregisters a section (tiles + buy buttons) against the sharedShopdispatch layer.CashHandler.luais the server-side grant logic theProductServicedispatches to on purchase.- The
ProductIdnumbers above are placeholder tokens — see Step 4.
Because everything is additive drop-in files, this extension needs no shared-file edits, so its Instructions.md is minimal.
Step 4 — Dev products upload (primary method)
Each dev product must be created by the experience owner. Cash Pack uses the primary token + source_path method: after the user creates each product, its placeholder ID in CashProducts.lua is replaced in-place.
[
{
"display_name": "Cash1 - 2,500 Cash",
"description": "Adds 2,500 cash",
"token": "3485188014",
"source_path": "ReplicatedStorage/SharedSource/Datas/Monetization/DevProductSets/CashProducts.lua",
"suggested_price": 49
}
]Each entry's token is the exact placeholder string that appears in the file at source_path. See Developer products for the full contract.
Checklist
relevant_systems.jsonrequires the handler and every system you rely on (currency, shop UI).- One drop-in file per extension point: product set, shop section, server handler — all uniquely named.
- Placeholder
ProductIdtokens in the product set match thetokenvalues in the upload metadata. To_Upload_By_User/DevProducts/superbullet_metadata.jsonhas correcttoken+source_path+suggested_price.metadata.jsonhasname,description, and a bumpedversion_number.