Quick donation board - Monetize in a snap!

hey i did a custom donation board (changes on UI) + a dancing rig (only one which would make it good and neat)

1 Like

How? I want to make it orange, I tried any way I can think off but the color doesn’t change.
Edit: nevermind I figure it out, sorry.

how do I make the board smaller without it messing up the ui

Wow that’s amazing! I like the UI as its neat and clean. I’ll be sure to use this in my future games, with your credit, of course!

Good job!

1 Like

It doesn’t work, most of the donation doesn’t show up

Is there a way to remove someone from the donation board???
I’ve donated in Studio as a test and it saved it without me wanting it to.

You can remove their key (UserId) from the OrderedDataStore.

How would I go about doing this exactly? I’ve seen something about using the :RemoveAysnc() feature, but I don’t quite know where that goes or how it really works.

I’ve tried something similar to this already and it makes no difference:

Could you post the script you ran?

This is the full Core code (minus the dev products). The key bit is down the very bottom.

local DataStoreService = game:GetService("DataStoreService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")

local gui = script.Donations
local face = Enum.NormalId[GUI_FACE]

local eve = Instance.new("RemoteEvent")
eve.Name = "DonationEvent"
eve.Parent = ReplicatedStorage

local cache = {}

local tmType = Enum.ThumbnailType.HeadShot
local tmSize = Enum.ThumbnailSize.Size420x420

local donations = DataStoreService:GetOrderedDataStore("DONATIONS_" .. DATA_KEY)

if not face then error("Invalid GUI_FACE: " .. GUI_FACE) else gui.Face = face end

local function getName(id)
	for cachedId, name in pairs (cache) do
		if cachedId == id then
			return name
	local success, result = pcall(function()
		return Players:GetNameFromUserIdAsync(id)
	if success then
		cache[id] = result
		return result
		warn(result .. "\nId: " .. id)
		return "N/A"

local function findAmountById(id)
	for _, donationInfo in pairs (DONATION_OPTIONS) do
		if donationInfo.Id == id then
			return donationInfo.Amount
	warn("Couldn't find donation amount for product ID " .. id)
	return 0

local function clearList(list)
	for _, v in pairs (list:GetChildren()) do
		if v:IsA("Frame") then v:Destroy() end

local function updateAllClients(page)
	eve:FireAllClients("update", page)

local function updateInternalBoard(updateClientsAfter)
	local sorted = donations:GetSortedAsync(false, math.clamp(DISPLAY_AMOUNT, 0, 250), 1)
	if sorted then
		local page = sorted:GetCurrentPage()
		local clientDataPacket = {}
		for rank, data in ipairs(page) do
			local userId = data.key
			local username = getName(data.key)
			local icon, isReady = Players:GetUserThumbnailAsync(userId, tmType, tmSize)
			local amountDonated = data.value .. " robux"

			local clone = gui.Main.Leaderboard.Template:Clone()
			clone.Icon.Image = icon
			clone.Rank.Text = "#" .. rank
			clone.Robux.Text = amountDonated
			clone.Username.Text = username
			clone.LayoutOrder = rank
			clone.Visible = true
			clone.Parent = gui.Main.Leaderboard.List
			table.insert(clientDataPacket, {
				["name"] = username,
				["icon"] = icon,
				["amount"] = amountDonated,
				["rank"] = rank
		if updateClientsAfter then
		warn("No data available for leaderboard refresh!")

local function createButtonsInternal()
	for pos, donationInfo in pairs (DONATION_OPTIONS) do
		local clone = gui.Main.Donate.Template:Clone()

		clone.Id.Value = donationInfo.Id
		clone.Info.Text = "<b>" .. donationInfo.Amount .. "</b> robux"

		clone.Visible = true
		clone.LayoutOrder = pos

		clone.Parent = gui.Main.Donate.List

local function processReceipt(receiptInfo) 
	local donatedAmount = findAmountById(receiptInfo.ProductId)
	local id = receiptInfo.PlayerId

	local success, err = pcall(function()
		donations:UpdateAsync(id, function(previousData)
			if previousData then
				return previousData + donatedAmount
				return donatedAmount

	local player = Players:GetPlayerByUserId(id)

	if not success then
		if player then
			eve:FireClient(player, "Error", "There was an error processing your purchase. You have not been charged. Error: " .. err)
		warn("Error handling " .. id .. "'s purchase: " .. err)
		return Enum.ProductPurchaseDecision.NotProcessedYet

	if player then
		eve:FireClient(player, "Success", "Thanks for your generous donation!")

	return Enum.ProductPurchaseDecision.PurchaseGranted

local function onPlayerAdded(plr)
	local pGui = plr:WaitForChild("PlayerGui", 5)
	if pGui then
		for _, board in pairs (script.Parent:GetChildren()) do
			if board.Name == "Board" then
				local clone = gui:Clone()
				clone.Adornee = board
				clone.Parent = pGui
		return true
	warn("Couldn't find PlayerGui for " .. plr.Name .. ":" .. plr.UserId)

MarketplaceService.ProcessReceipt = processReceipt

for _, plr in pairs (Players:GetPlayers()) do

while true do

local success, removedValue = pcall(function()
	return donations:RemoveAsync("User_336700386")
if success then

Where are you getting the “User_” from? And why is it a string?

I saw on a different post that was how it was done…
I’m assuming that is very incorrect.

how to make top player? show npc
like this :

I’ve made donations in studio and I don’t know how to get rid of them without changing the datastore completely and erasing real donations from other users. I’ve tried using SetAsync and UpdateAsync, but I don’t have too much experience in datastores at the moment and to my understanding, it’s not working when I try. How can I get rid of donations without removing all of them?

EDIT: I was able to fix the issue with this amazing datastore plugin. I suggest you check it out, it’s very useful.

1 Like

Thank you for suggesting my plugin! :slight_smile:


This was described in an earlier post.

Hi, awesome system - only recommendation, add themes!

A way I did this with a system I made (FoodMate) was have a folder with UI gradients with different names, add in default ones and the customer can make their own ones if they like, and basically put a stringValue in each component to copy the UI gradient into named “ThemePart” and whenever you startup the system it detects the theme selected (possibly just another config thing) and finds all “ThemePart”'s and then just clones in the selected UI gradient.

I know this would be the most annoying suggestion and I also made it a lot more complicated than it needed to be because you can script it without me spoonfeeding it to u lmfao

The ONLY semi issue I found was when I added multiple boards, the congratulations notification appeared on all of them and I had to manually press dismiss on each and every board. Possibly just add a bindable function somewhere that will auto hide them all when you dismiss one notification.

1 Like

Dont mind the background music was listening to some heavy base boost’d stuff…

@twinqle, this is what i’ve made of your donation lb. (Just added a lil effect ;))


hey man how can i use my already created datastore has all my players donations already in it . i wanna use your board instead but mine at the moment only called the datastore by its name “datastorenamehere” in this format ty

Hey for some reason when i have this board in my game, other developer product functions breaks and doesn’t work! Help!