Cara Membuat Overlay Kustom
Mau stream kamu makin kece dengan overlay buatan sendiri? Custom overlay ini kayak kanvas kosong buat kamu berkreasi pake HTML. Bisa buat pesan spesial, animasi seru, atau branding yang bikin orang langsung inget sama kamu!
Apa Saja Jenis Overlay yang Dapat Dikustomisasi?
- Alert (Tidak termasuk media seperti Voice Note ataupun GIF)
- Media Share (Hanya bagian pesan, bagian media/video dan progress bar tidak dapat di custom)
- Leaderboard
- Timer (Akan re-rendered setiap kali waktu berubah)
- Soundboard
- Milestone
- Polling
- Running Text
- VIP Queue
- Song Share (Info lagu, antrian, dan player visual, progress bar, play/pause, cover art )
Tips Penulisan Kode HTML
- Gunakan struktur HTML standar: Selalu mulai dengan
<html>,<head>, dan<body>. - Jangan pake
position: absolutedi CSS Body: Pastikan body memiliki height yang pasti karena sistem overlay Tako akan mendeteksi ukuran body, jika ukuran body tidak dapat di deteksi maka overlay akan tidak tampil karena sistem overlay Tako menganggap ukuran tinggi body sebesar 0px apabila body menggunakan posisi absolute. - Gunain ukuran fleksibel: Gunakan
px,rem, atauembuat font atau elemen. Jangan gunakanvhatauvw. - Biasakan gunakan ukuran
remkarena agar mudah di scaling melalui pengaturan ukuran font di dashboard pengaturan overlay. - Selalu tes di dashboard biar tampilan sesuai dengan harapan.
- Jangan pake komentar
//di dalam<script>: Sistem overlay Tako menghapus semua baris baru (newline) dari kode kamu sebelum dirender. Komentar//cuma berhenti di baris baru — begitu newline-nya hilang, komentar itu bisa "menelan" sisa kode di bawahnya sampai akhir script, bikin logic sesudahnya gak jalan tanpa ada error yang kelihatan. Kalo mau komentar, pake/* ... */, atau lebih aman gak usah pake komentar sama sekali. - Data JSON (array/objek) langsung ditulis literal, jangan dibungkus tanda kutip: Tulis
const data = {{namaVariabel}};— BUKANconst data = JSON.parse('{{namaVariabel}}'). Isi JSON udah pasti pake tanda kutip dua ("), dan itu bakal motong string JS kamu di tengah kalo dibungkus kutip lagi, bikin script error. - Jangan kasih
max-widthfixed di container utama: Ukuran box overlay (lebar/tinggi) udah kamu tentuin sendiri lewat OBS Browser Source atau dashboard preview. Kalo kode kamu pakemax-widthtetap (misal26rem), box-nya bakal mentok di situ dan nyisain ruang kosong kalo box asli lebih lebar. Pakewidth: 100%biar ngisi penuh ukuran box yang udah kamu atur.
Variabel untuk Setiap Overlay
Tiap overlay punya variabel yang bisa kamu pake biar tampilan dinamis tanpa edit manual. Berikut daftar lengkapnya, termasuk overlay yang mendukung dan contoh penggunaan:
⚠️ Pastikan tidak ada spasi antara kurung kurawal dengan nama variabel!
1. Alert & Media Share
Nama Variabel | Contoh Info | Keterangan |
|---|---|---|
|
| Jumlah donasi (angka mentah). |
|
| Jumlah donasi yang sudah diformat. |
|
| Pesan dari donatur. |
|
| Nama donatur. |
| Link foto profil donatur. | |
|
| Daftar badge donatur (nama doang, dipisah koma) — gak ada URL ikon dari sistem. |
|
| Status verifikasi donatur ( |
|
| Durasi media pada alert/mediashare; jika tidak ada media, jadi durasi alertnya. |
⚠️ Tako gak ngirim URL ikon badge. Kalo mau badge tampil sebagai gambar (bukan teks/tag), isi manual di BADGE_ICON_URLS dalam script di bawah: key = nama badge persis kayak yang keluar di {{gifterBadges}}, value = URL ikon badge itu. Badge yang gak ada di daftar itu otomatis fallback ke tag teks biasa.
Contoh kode di bawah udah diisiin 6 badge sistem resmi Tako (nama + URL):
Nama Badge | URL Ikon |
|---|---|
| |
| |
| |
| |
| |
|
Contoh Kode:
<html>
<head>
<style>
body { margin: 0; background: none; font-family: "Courier New", monospace; color: #1c1712; }
.ticket {
position: relative;
width: 100%;
box-sizing: border-box;
overflow: hidden;
background: #f2e9d3;
border: 2px solid #1c1712;
box-shadow: 0.2rem 0.25rem 0 0 #1c1712;
padding: 0.9rem 1rem 0.9rem 1.5rem;
}
.tab { position: absolute; left: 0; top: 0; bottom: 0; width: 0.55rem; background: #9c3b2e; border-right: 2px solid #1c1712; }
.grommet { position: absolute; left: 0.275rem; top: 0.85rem; width: 0.4rem; height: 0.4rem; border-radius: 50%; background: #f2e9d3; border: 1px solid #1c1712; transform: translate(-50%, 0); z-index: 2; }
.gifter-row { display: flex; align-items: center; gap: 0.6rem; }
.avatar { width: 2.6rem; height: 2.6rem; border-radius: 50%; border: 2px solid #1c1712; object-fit: cover; flex-shrink: 0; display: none; }
.avatar-fallback { width: 2.6rem; height: 2.6rem; border-radius: 50%; border: 2px solid #1c1712; background: #e8dab8; flex-shrink: 0; display: flex; align-items: center; justify-content: center; font-size: 1.25rem; }
.gifter-info { flex: 1; min-width: 0; }
.gifter-name { font-weight: 700; font-size: 1.0625rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.badges { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; margin-top: 0.2rem; }
.badge-tag { font-size: 0.75rem; border: 1px solid #7a7160; color: #7a7160; padding: 0.05rem 0.35rem; }
.badge-icon { height: 1rem; width: auto; display: block; }
.amount { font-weight: 700; font-size: 1.125rem; color: #b6842c; flex-shrink: 0; }
.perf { border-bottom: 1px dashed #7a7160; margin: 0.6rem 0; }
.message { font-size: 1rem; color: #4a4335; }
.media-tag { display: inline-block; margin-top: 0.4rem; font-size: 0.75rem; color: #7a7160; border: 1px solid #7a7160; padding: 0.05rem 0.35rem; }
</style>
</head>
<body>
<div class="ticket">
<div class="tab"></div>
<div class="grommet"></div>
<div class="gifter-row">
<img class="avatar" id="avatar" alt="">
<span class="avatar-fallback" id="avatar-fallback">🎁</span>
<div class="gifter-info">
<div class="gifter-name" id="gifter-name">{{gifterName}}</div>
<div class="badges" id="badges"></div>
</div>
<div class="amount">{{formattedAmount}}</div>
</div>
<div class="perf"></div>
<div class="message" id="message">{{message}}</div>
<div class="media-tag" id="media-tag"></div>
</div>
<script>
const picture = "{{gifterPicture}}".trim();
const badgesRaw = "{{gifterBadges}}".trim();
const isVerified = "{{isGifterVerified}}" === "true";
const mediaDuration = "{{mediaDuration}}";
const BADGE_ICON_URLS = {
"Tako Verified Partner": "https://tako.id/images/badges/partnered-creator.png",
"Tako Verified Creator": "https://tako.id/images/badges/verified-creator.png",
"Rich Rich Club": "https://tako.id/images/badges/king.png",
"Charity": "https://tako.id/images/badges/charity.png",
"VTuber": "https://tako.id/images/badges/vtuber.png",
"Tako Team": "https://tako.id/images/badges/admin.png"
};
const avatar = document.getElementById("avatar");
const avatarFallback = document.getElementById("avatar-fallback");
const gifterName = document.getElementById("gifter-name");
const badgesEl = document.getElementById("badges");
const messageEl = document.getElementById("message");
const mediaTag = document.getElementById("media-tag");
if (picture && !picture.includes("{{")) {
avatar.src = picture;
avatar.style.display = "block";
avatarFallback.style.display = "none";
avatar.onerror = () => {
avatar.style.display = "none";
avatarFallback.style.display = "flex";
};
}
if (isVerified) gifterName.appendChild(document.createTextNode(" ✓"));
if (badgesRaw && !badgesRaw.includes("{{")) {
badgesRaw.split(",").filter(Boolean).forEach((name) => {
const iconUrl = BADGE_ICON_URLS[name];
if (iconUrl) {
const icon = document.createElement("img");
icon.className = "badge-icon";
icon.src = iconUrl;
icon.alt = name;
icon.title = name;
badgesEl.appendChild(icon);
} else {
const tag = document.createElement("span");
tag.className = "badge-tag";
tag.textContent = name;
badgesEl.appendChild(tag);
}
});
}
if (!messageEl.textContent.trim() || messageEl.textContent.includes("{{")) {
messageEl.style.display = "none";
}
if (mediaDuration && !mediaDuration.includes("{{") && Number(mediaDuration) > 0) {
mediaTag.textContent = "⏱ " + mediaDuration + "s";
} else {
mediaTag.style.display = "none";
}
</script>
</body>
</html>
2. Leaderboard
Nama Variabel | Contoh Info | Keterangan |
|---|---|---|
|
| Judul leaderboard dari pengaturan. |
|
| Daftar ranking (JSON): nama, foto, badge (nama doang, dipisah koma — gak ada URL ikon), jumlah donasi, jumlah donasi diformat. |
Contoh Kode:
<html>
<head>
<style>
body { margin: 0; background: none; font-family: "Courier New", monospace; color: #1c1712; }
.ticket {
position: relative;
width: 100%;
box-sizing: border-box;
overflow: hidden;
background: #f2e9d3;
border: 2px solid #1c1712;
box-shadow: 0.2rem 0.25rem 0 0 #1c1712;
padding: 0.9rem 1rem 0.9rem 1.5rem;
}
.tab { position: absolute; left: 0; top: 0; bottom: 0; width: 0.55rem; background: #9c3b2e; border-right: 2px solid #1c1712; }
.grommet { position: absolute; left: 0.275rem; top: 0.85rem; width: 0.4rem; height: 0.4rem; border-radius: 50%; background: #f2e9d3; border: 1px solid #1c1712; transform: translate(-50%, 0); z-index: 2; }
.title { font-size: 1.0625rem; font-weight: 700; }
.perf { border-bottom: 1px dashed #7a7160; margin: 0.6rem 0; }
.rank-row { display: flex; align-items: center; gap: 0.6rem; font-size: 1rem; padding: 0.35rem 0; border-bottom: 1px dashed #e8dab8; }
.rank-row:last-child { border-bottom: none; }
.rank-num { width: 1.6rem; font-weight: 700; color: #b6842c; flex-shrink: 0; }
.rank-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rank-badges { display: flex; align-items: center; gap: 0.2rem; flex-shrink: 0; }
.rank-badge-tag { font-size: 0.75rem; border: 1px solid #7a7160; color: #7a7160; padding: 0.05rem 0.35rem; }
.rank-badge-icon { height: 0.9375rem; width: auto; display: block; }
.rank-amount { font-weight: 700; color: #7a7160; flex-shrink: 0; }
</style>
</head>
<body>
<div class="ticket">
<div class="tab"></div>
<div class="grommet"></div>
<div class="title" id="lb-title">{{title}}</div>
<div class="perf"></div>
<div id="lb-list"></div>
</div>
<script>
const rankings = {{rankings}};
const list = document.getElementById("lb-list");
const BADGE_ICON_URLS = {
"Tako Verified Partner": "https://tako.id/images/badges/partnered-creator.png",
"Tako Verified Creator": "https://tako.id/images/badges/verified-creator.png",
"Rich Rich Club": "https://tako.id/images/badges/king.png",
"Charity": "https://tako.id/images/badges/charity.png",
"VTuber": "https://tako.id/images/badges/vtuber.png",
"Tako Team": "https://tako.id/images/badges/admin.png"
};
rankings.forEach((r, i) => {
const row = document.createElement("div");
row.className = "rank-row";
const num = document.createElement("span");
num.className = "rank-num";
num.textContent = "#" + (i + 1);
const name = document.createElement("span");
name.className = "rank-name";
name.textContent = r.name;
const badges = document.createElement("div");
badges.className = "rank-badges";
(r.badges || "").split(",").filter(Boolean).forEach((badgeName) => {
const iconUrl = BADGE_ICON_URLS[badgeName];
if (iconUrl) {
const icon = document.createElement("img");
icon.className = "rank-badge-icon";
icon.src = iconUrl;
icon.alt = badgeName;
icon.title = badgeName;
badges.appendChild(icon);
} else {
const tag = document.createElement("span");
tag.className = "rank-badge-tag";
tag.textContent = badgeName;
badges.appendChild(tag);
}
});
const amount = document.createElement("span");
amount.className = "rank-amount";
amount.textContent = r.formattedAmount;
row.appendChild(num);
row.appendChild(name);
row.appendChild(badges);
row.appendChild(amount);
list.appendChild(row);
});
</script>
</body>
</html>
3. Milestone
Nama Variabel | Contoh Info | Keterangan |
|---|---|---|
|
| Judul milestone dari pengaturan. |
|
| Total donasi terkumpul dari semua langkah (angka mentah). |
|
| Total donasi terkumpul, diformat. |
|
| Total target dari semua langkah (angka mentah). |
|
| Total target, diformat. |
|
| Persentase progres keseluruhan (0-100, bisa lebih dari 100 kalo kelebihan). |
|
| Progres dalam langkah yang sedang aktif saja (angka mentah). |
|
| Progres langkah aktif, diformat. |
|
| Target langkah yang sedang aktif (angka mentah). |
|
| Target langkah aktif, diformat. |
|
| Persentase progres langkah aktif (0-100). |
|
| Nomor urut langkah aktif (mulai dari 1). |
|
| Total jumlah langkah. |
|
| Judul langkah yang sedang aktif (kosong kalo gak diset). |
|
| Daftar semua langkah (JSON), tiap item punya |
Contoh Kode:
<html>
<head>
<style>
body { margin: 0; background: none; font-family: "Courier New", monospace; color: #1c1712; }
.ticket {
position: relative;
width: 100%;
box-sizing: border-box;
overflow: hidden;
background: #f2e9d3;
border: 2px solid #1c1712;
box-shadow: 0.2rem 0.25rem 0 0 #1c1712;
padding: 0.9rem 1rem 0.9rem 1.5rem;
}
.tab { position: absolute; left: 0; top: 0; bottom: 0; width: 0.55rem; background: #9c3b2e; border-right: 2px solid #1c1712; }
.grommet { position: absolute; left: 0.275rem; top: 0.85rem; width: 0.4rem; height: 0.4rem; border-radius: 50%; background: #f2e9d3; border: 1px solid #1c1712; transform: translate(-50%, 0); z-index: 2; }
.title { font-size: 1.0625rem; font-weight: 700; }
.perf { border-bottom: 1px dashed #7a7160; margin: 0.6rem 0; }
.bar-bg { height: 0.7rem; background: #e8dab8; border: 1px solid #1c1712; }
.bar-fill { height: 100%; background: #b6842c; }
.amounts { display: flex; justify-content: space-between; font-size: 1rem; font-weight: 700; margin-top: 0.45rem; }
.meta { font-size: 0.8125rem; color: #7a7160; margin-top: 0.45rem; }
</style>
</head>
<body>
<div class="ticket">
<div class="tab"></div>
<div class="grommet"></div>
<div class="title" id="ms-title">{{title}}</div>
<div class="perf"></div>
<div class="bar-bg">
<div class="bar-fill" id="bar-fill" style="width: {{percentage}}%"></div>
</div>
<div class="amounts">
<span id="current">{{formattedStepProgress}}</span>
<span id="target">{{formattedStepTarget}}</span>
</div>
<div class="meta">Langkah {{stepIndex}} / {{stepCount}}</div>
</div>
</body>
</html>
4. Polling
Nama Variabel | Contoh Info | Keterangan |
|---|---|---|
|
| Judul polling dari pengaturan. |
|
| Daftar opsi polling (JSON): ID, nama, jumlah donasi, jumlah donasi diformat. |
|
| Tanggal mulai polling. |
|
| Waktu mulai polling. |
|
| Tanggal selesai polling. |
|
| Waktu selesai polling. |
Contoh Kode:
<html>
<head>
<style>
body { margin: 0; background: none; font-family: "Courier New", monospace; color: #1c1712; }
.ticket {
position: relative;
width: 100%;
box-sizing: border-box;
overflow: hidden;
background: #f2e9d3;
border: 2px solid #1c1712;
box-shadow: 0.2rem 0.25rem 0 0 #1c1712;
padding: 0.9rem 1rem 0.9rem 1.5rem;
}
.tab { position: absolute; left: 0; top: 0; bottom: 0; width: 0.55rem; background: #9c3b2e; border-right: 2px solid #1c1712; }
.grommet { position: absolute; left: 0.275rem; top: 0.85rem; width: 0.4rem; height: 0.4rem; border-radius: 50%; background: #f2e9d3; border: 1px solid #1c1712; transform: translate(-50%, 0); z-index: 2; }
.title { font-size: 1.0625rem; font-weight: 700; }
.perf { border-bottom: 1px dashed #7a7160; margin: 0.6rem 0; }
.poll-row { display: flex; align-items: center; gap: 0.6rem; font-size: 1rem; padding: 0.35rem 0; border-bottom: 1px dashed #e8dab8; }
.poll-row:last-child { border-bottom: none; }
.poll-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.poll-amount { font-weight: 700; color: #7a7160; flex-shrink: 0; }
.meta { font-size: 0.8125rem; color: #7a7160; margin-top: 0.55rem; }
</style>
</head>
<body>
<div class="ticket">
<div class="tab"></div>
<div class="grommet"></div>
<div class="title" id="poll-title">{{title}}</div>
<div class="perf"></div>
<div id="poll-list"></div>
<div class="meta">{{startAt}} {{startTime}} — {{endAt}} {{endTime}}</div>
</div>
<script>
const options = {{pollingOptions}};
const list = document.getElementById("poll-list");
options.forEach((o) => {
const row = document.createElement("div");
row.className = "poll-row";
const name = document.createElement("span");
name.className = "poll-name";
name.textContent = o.name;
const amount = document.createElement("span");
amount.className = "poll-amount";
amount.textContent = o.formattedTotalAmount;
row.appendChild(name);
row.appendChild(amount);
list.appendChild(row);
});
</script>
</body>
</html>
5. Running Text
Nama Variabel | Contoh Info | Keterangan |
|---|---|---|
|
| Daftar teks tambahan (JSON): judul, warna latar, warna teks. |
|
| Daftar donasi (JSON): nama donatur, jumlah donasi, jumlah donasi diformat. |
Contoh Kode:
<html>
<head>
<style>
body { margin: 0; background: none; font-family: "Courier New", monospace; color: #1c1712; overflow: hidden; }
.ticker {
position: relative;
width: 100%;
box-sizing: border-box;
background: #f2e9d3;
border-top: 2px solid #1c1712;
border-bottom: 2px solid #1c1712;
padding: 0.6rem 0 0.6rem 1.4rem;
overflow: hidden;
white-space: nowrap;
}
.tab { position: absolute; left: 0; top: 0; bottom: 0; width: 0.55rem; background: #9c3b2e; border-right: 2px solid #1c1712; }
.grommet { position: absolute; left: 0.275rem; top: 50%; width: 0.4rem; height: 0.4rem; border-radius: 50%; background: #f2e9d3; border: 1px solid #1c1712; transform: translate(-50%, -50%); z-index: 2; }
.ticker-track { display: inline-flex; gap: 1.5rem; animation: scroll 18s linear infinite; }
.ticker-item { font-size: 1rem; font-weight: 700; flex-shrink: 0; }
.ticker-item.gift { color: #9c3b2e; }
@keyframes scroll {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
</style>
</head>
<body>
<div class="ticker">
<div class="tab"></div>
<div class="grommet"></div>
<div class="ticker-track" id="track"></div>
</div>
<script>
const texts = {{texts}};
const gifts = {{gifts}};
const track = document.getElementById("track");
function buildItems() {
const frag = document.createDocumentFragment();
texts.forEach((t) => {
const item = document.createElement("span");
item.className = "ticker-item";
item.style.color = t.textColor || "#1c1712";
item.textContent = t.title;
frag.appendChild(item);
});
gifts.forEach((g) => {
const item = document.createElement("span");
item.className = "ticker-item gift";
item.textContent = g.gifterName + " — " + g.formattedAmount;
frag.appendChild(item);
});
return frag;
}
track.appendChild(buildItems());
track.appendChild(buildItems());
</script>
</body>
</html>
Dua kali buildItems() di-append itu buat scroll seamless (dua salinan isi bersebelahan, translateX(-50%) berhenti pas salinan kedua persis nyampe posisi salinan pertama). Overlay ini gak ada progress-tick per-250ms kayak Song Share, jadi CSS animation loop aman jalan terus tanpa restart.
6. Soundboard
Nama Variabel | Contoh Info | Keterangan |
|---|---|---|
|
| Jumlah donasi (angka mentah). |
|
| Jumlah donasi yang diformat. |
|
| Nama efek suara yang dipilih. |
|
| Nama donatur. |
| Link foto profil donatur. | |
|
| Daftar badge donatur (nama doang, dipisah koma) — gak ada URL ikon dari sistem. |
|
| Status verifikasi donatur ( |
Contoh Kode:
<html>
<head>
<style>
body { margin: 0; background: none; font-family: "Courier New", monospace; color: #1c1712; }
.ticket {
position: relative;
width: 100%;
box-sizing: border-box;
overflow: hidden;
background: #f2e9d3;
border: 2px solid #1c1712;
box-shadow: 0.2rem 0.25rem 0 0 #1c1712;
padding: 0.9rem 1rem 0.9rem 1.5rem;
}
.tab { position: absolute; left: 0; top: 0; bottom: 0; width: 0.55rem; background: #9c3b2e; border-right: 2px solid #1c1712; }
.grommet { position: absolute; left: 0.275rem; top: 0.85rem; width: 0.4rem; height: 0.4rem; border-radius: 50%; background: #f2e9d3; border: 1px solid #1c1712; transform: translate(-50%, 0); z-index: 2; }
.gifter-row { display: flex; align-items: center; gap: 0.6rem; }
.avatar { width: 2.6rem; height: 2.6rem; border-radius: 50%; border: 2px solid #1c1712; object-fit: cover; flex-shrink: 0; display: none; }
.avatar-fallback { width: 2.6rem; height: 2.6rem; border-radius: 50%; border: 2px solid #1c1712; background: #e8dab8; flex-shrink: 0; display: flex; align-items: center; justify-content: center; font-size: 1.25rem; }
.gifter-info { flex: 1; min-width: 0; }
.gifter-name { font-weight: 700; font-size: 1.0625rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.badges { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; margin-top: 0.2rem; }
.badge-tag { font-size: 0.75rem; border: 1px solid #7a7160; color: #7a7160; padding: 0.05rem 0.35rem; }
.badge-icon { height: 1rem; width: auto; display: block; }
.amount { font-weight: 700; font-size: 1.125rem; color: #b6842c; flex-shrink: 0; }
.perf { border-bottom: 1px dashed #7a7160; margin: 0.6rem 0; }
.sound-name { font-size: 1.0625rem; font-weight: 700; }
</style>
</head>
<body>
<div class="ticket">
<div class="tab"></div>
<div class="grommet"></div>
<div class="gifter-row">
<img class="avatar" id="avatar" alt="">
<span class="avatar-fallback" id="avatar-fallback">🔊</span>
<div class="gifter-info">
<div class="gifter-name" id="gifter-name">{{gifterName}}</div>
<div class="badges" id="badges"></div>
</div>
<div class="amount">{{formattedAmount}}</div>
</div>
<div class="perf"></div>
<div class="sound-name">🔈 {{soundName}}</div>
</div>
<script>
const picture = "{{gifterPicture}}".trim();
const badgesRaw = "{{gifterBadges}}".trim();
const isVerified = "{{isGifterVerified}}" === "true";
const BADGE_ICON_URLS = {
"Tako Verified Partner": "https://tako.id/images/badges/partnered-creator.png",
"Tako Verified Creator": "https://tako.id/images/badges/verified-creator.png",
"Rich Rich Club": "https://tako.id/images/badges/king.png",
"Charity": "https://tako.id/images/badges/charity.png",
"VTuber": "https://tako.id/images/badges/vtuber.png",
"Tako Team": "https://tako.id/images/badges/admin.png"
};
const avatar = document.getElementById("avatar");
const avatarFallback = document.getElementById("avatar-fallback");
const gifterName = document.getElementById("gifter-name");
const badgesEl = document.getElementById("badges");
if (picture && !picture.includes("{{")) {
avatar.src = picture;
avatar.style.display = "block";
avatarFallback.style.display = "none";
avatar.onerror = () => {
avatar.style.display = "none";
avatarFallback.style.display = "flex";
};
}
if (isVerified) gifterName.appendChild(document.createTextNode(" ✓"));
if (badgesRaw && !badgesRaw.includes("{{")) {
badgesRaw.split(",").filter(Boolean).forEach((name) => {
const iconUrl = BADGE_ICON_URLS[name];
if (iconUrl) {
const icon = document.createElement("img");
icon.className = "badge-icon";
icon.src = iconUrl;
icon.alt = name;
icon.title = name;
badgesEl.appendChild(icon);
} else {
const tag = document.createElement("span");
tag.className = "badge-tag";
tag.textContent = name;
badgesEl.appendChild(tag);
}
});
}
</script>
</body>
</html>
7. Timer
Nama Variabel | Contoh Info | Keterangan |
|---|---|---|
|
| Judul timer dari pengaturan. |
|
| Sisa waktu dalam format |
|
| Status timer ( |
|
| Daftar opsi timer (JSON): durasi tambahan (ms), jumlah donasi minimum untuk menambah waktu. |
Contoh Kode:
<html>
<head>
<style>
body { margin: 0; background: none; font-family: "Courier New", monospace; color: #1c1712; }
.ticket {
position: relative;
width: 100%;
box-sizing: border-box;
overflow: hidden;
background: #f2e9d3;
border: 2px solid #1c1712;
box-shadow: 0.2rem 0.25rem 0 0 #1c1712;
padding: 0.9rem 1rem 0.9rem 1.5rem;
text-align: center;
}
.tab { position: absolute; left: 0; top: 0; bottom: 0; width: 0.55rem; background: #9c3b2e; border-right: 2px solid #1c1712; }
.grommet { position: absolute; left: 0.275rem; top: 0.85rem; width: 0.4rem; height: 0.4rem; border-radius: 50%; background: #f2e9d3; border: 1px solid #1c1712; transform: translate(-50%, 0); z-index: 2; }
.row-head { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; text-align: left; }
.title { flex: 1; min-width: 0; font-size: 1.0625rem; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.status { flex-shrink: 0; font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; color: #7a7160; border: 1px solid #7a7160; padding: 0.1rem 0.4rem; }
.perf { border-bottom: 1px dashed #7a7160; margin: 0.6rem 0; }
.countdown { font-size: 2.25rem; font-weight: 700; letter-spacing: 0.05em; }
</style>
</head>
<body>
<div class="ticket">
<div class="tab"></div>
<div class="grommet"></div>
<div class="row-head">
<span class="title" id="timer-title">{{title}}</span>
<span class="status" id="status-el">Active</span>
</div>
<div class="perf"></div>
<div class="countdown">{{timeLeft}}</div>
</div>
<script>
const isEnabled = "{{isEnabled}}" === "true";
document.getElementById("status-el").textContent = isEnabled ? "Active" : "Inactive";
</script>
</body>
</html>
8. VIP Queue
Nama Variabel | Contoh Info | Keterangan |
|---|---|---|
|
| Judul dari pengaturan. |
|
| Total jumlah orang dalam antrian. |
|
| Jumlah entri yang gak ditampilin karena kelebihan limit ( |
|
| Status apakah custom field (misal alamat, catatan) ditampilkan. |
|
| Daftar antrian yang sudah dipotong sesuai limit tampilan (JSON) — dipake buat render. Tiap entri punya |
| sama struktur kayak | Daftar semua antrian (JSON), belum dipotong limit. |
|
| Semua custom field dari semua entri, digabung jadi satu array datar (JSON). |
Contoh Kode:
<html>
<head>
<style>
body { margin: 0; background: none; font-family: "Courier New", monospace; color: #1c1712; }
.ticket {
position: relative;
width: 100%;
box-sizing: border-box;
overflow: hidden;
background: #f2e9d3;
border: 2px solid #1c1712;
box-shadow: 0.2rem 0.25rem 0 0 #1c1712;
padding: 0.9rem 1rem 0.9rem 1.5rem;
}
.tab { position: absolute; left: 0; top: 0; bottom: 0; width: 0.55rem; background: #9c3b2e; border-right: 2px solid #1c1712; }
.grommet { position: absolute; left: 0.275rem; top: 0.85rem; width: 0.4rem; height: 0.4rem; border-radius: 50%; background: #f2e9d3; border: 1px solid #1c1712; transform: translate(-50%, 0); z-index: 2; }
.row-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.title { font-size: 1.0625rem; font-weight: 700; }
.count-badge { font-size: 0.875rem; font-weight: 700; color: #b6842c; border: 1px solid #7a7160; padding: 0.05rem 0.45rem; border-radius: 999px; flex-shrink: 0; }
.perf { border-bottom: 1px dashed #7a7160; margin: 0.6rem 0; }
.queue-list { display: flex; flex-direction: column; gap: 0.5rem; }
.queue-row { display: flex; align-items: center; gap: 0.5rem; }
.queue-num { width: 1.5rem; height: 1.5rem; border-radius: 50%; background: #e8dab8; border: 1px solid #1c1712; flex-shrink: 0; display: flex; align-items: center; justify-content: center; font-size: 0.75rem; font-weight: 700; }
.queue-avatar { width: 1.6rem; height: 1.6rem; border-radius: 50%; border: 1px solid #1c1712; object-fit: cover; flex-shrink: 0; display: none; }
.queue-name { flex: 1; min-width: 0; font-size: 1rem; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.queue-badges { display: flex; align-items: center; gap: 0.2rem; flex-shrink: 0; }
.queue-badge-icon { height: 1.0625rem; width: auto; display: block; }
.queue-amount { font-size: 0.875rem; font-weight: 700; color: #7a7160; flex-shrink: 0; }
.queue-fields { font-size: 0.75rem; color: #7a7160; padding-left: 2.1rem; }
.queue-empty { font-size: 1rem; font-style: italic; color: #7a7160; }
.hidden-note { font-size: 0.8125rem; text-align: center; color: #7a7160; font-weight: 700; margin-top: 0.3rem; }
</style>
</head>
<body>
<div class="ticket">
<div class="tab"></div>
<div class="grommet"></div>
<div class="row-head">
<div class="title" id="queue-title">{{title}}</div>
<div class="count-badge" id="count-badge">{{totalEntries}}</div>
</div>
<div class="perf"></div>
<div class="queue-list" id="queue-list"></div>
<div class="hidden-note" id="hidden-note"></div>
</div>
<script>
const entries = {{visibleEntries}};
const hiddenCount = {{hiddenCount}};
const showFields = "{{showFields}}" === "true";
const list = document.getElementById("queue-list");
const hiddenNote = document.getElementById("hidden-note");
if (entries.length === 0) {
const empty = document.createElement("p");
empty.className = "queue-empty";
empty.textContent = "Belum ada antrian.";
list.appendChild(empty);
}
entries.forEach((entry) => {
const row = document.createElement("div");
row.className = "queue-row";
const num = document.createElement("div");
num.className = "queue-num";
num.textContent = entry.index;
const avatar = document.createElement("img");
avatar.className = "queue-avatar";
if (entry.picture) {
avatar.src = entry.picture;
avatar.style.display = "block";
avatar.onerror = () => { avatar.style.display = "none"; };
}
const name = document.createElement("span");
name.className = "queue-name";
name.textContent = entry.name + (entry.isVerified ? " ✓" : "");
const badgesEl = document.createElement("div");
badgesEl.className = "queue-badges";
(entry.badgeItems || []).forEach((badge) => {
if (!badge.url) return;
const icon = document.createElement("img");
icon.className = "queue-badge-icon";
icon.src = badge.url;
icon.alt = badge.title || "";
icon.title = badge.title || "";
badgesEl.appendChild(icon);
});
const amount = document.createElement("span");
amount.className = "queue-amount";
amount.textContent = entry.formattedAmount;
row.appendChild(num);
row.appendChild(avatar);
row.appendChild(name);
row.appendChild(badgesEl);
row.appendChild(amount);
list.appendChild(row);
if (showFields && entry.fields && entry.fields.length > 0) {
const fieldsRow = document.createElement("div");
fieldsRow.className = "queue-fields";
fieldsRow.textContent = entry.fields.map((f) => f.label + ": " + (f.value || "-")).join(" • ");
list.appendChild(fieldsRow);
}
});
if (hiddenCount > 0) {
hiddenNote.textContent = "+" + hiddenCount + " lainnya menunggu";
}
</script>
</body>
</html>
9. Song Share
Nama Variabel | Contoh Info | Keterangan |
|---|---|---|
|
| Judul lagu yang sedang diputar. |
|
| Nama artis lagu yang sedang diputar. |
| Link cover art lagu yang sedang diputar. | |
|
| Nama pe-request lagu. |
| Link foto profil pe-request. | |
|
| Daftar badge pe-request (nama doang, dipisah koma) — gak ada URL ikon dari sistem buat baris "Now Playing" ini. Isi manual di |
|
| Status verifikasi pe-request. |
|
| Durasi lagu (angka mentah). |
|
| Durasi lagu yang sudah diformat. |
|
| Waktu lagu yang sudah berjalan (angka mentah). |
|
| Waktu lagu yang sudah berjalan, diformat. |
|
| Persentase progres lagu (0-100) — pakai buat bikin progress bar sendiri. |
|
| Status lagu sedang diputar. |
|
| Status lagu sedang di-pause. |
|
| Status sedang dalam jeda antar lagu. |
|
| Sisa waktu jeda antar lagu. |
|
| Teks status jeda antar lagu. |
|
| Pesan error jika ada, kosong jika tidak ada. |
|
| Objek (JSON) lagu yang sedang diputar, |
|
| Daftar antrian lagu berikutnya (JSON). Tiap item punya |
Contoh Kode:
<html>
<head>
<style>
body { margin: 0; background: none; font-family: "Courier New", monospace; color: #1c1712; }
.ticket {
position: relative;
width: 100%;
box-sizing: border-box;
overflow: hidden;
background: #f2e9d3;
border: 2px solid #1c1712;
box-shadow: 0.2rem 0.25rem 0 0 #1c1712;
padding: 0.9rem 1rem 0.9rem 1.5rem;
}
.tab { position: absolute; left: 0; top: 0; bottom: 0; width: 0.55rem; background: #9c3b2e; border-right: 2px solid #1c1712; }
.grommet { position: absolute; left: 0.275rem; top: 0.85rem; width: 0.4rem; height: 0.4rem; border-radius: 50%; background: #f2e9d3; border: 1px solid #1c1712; transform: translate(-50%, 0); z-index: 2; }
.row-head { display: flex; justify-content: flex-end; margin-bottom: 0.5rem; }
.status { font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; color: #7a7160; border: 1px solid #7a7160; padding: 0.1rem 0.4rem; }
.error-banner { font-size: 0.8125rem; background: #9c3b2e; color: #f2e9d3; padding: 0.35rem 0.5rem; margin-bottom: 0.5rem; display: none; }
.gap-banner { font-size: 0.9375rem; color: #7a7160; padding: 0.4rem 0; display: none; }
.now-playing { display: flex; gap: 0.75rem; }
.cover { position: relative; width: 3.4rem; height: 3.4rem; flex-shrink: 0; background: #e8dab8; border: 2px solid #1c1712; display: flex; align-items: center; justify-content: center; font-size: 1.25rem; color: #7a7160; }
.cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: none; }
.info { flex: 1; min-width: 0; }
.title { font-size: 1.0625rem; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.title.idle { font-weight: 400; color: #7a7160; }
.artist { font-size: 0.9375rem; color: #7a7160; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 0.35rem; }
.requester { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; font-size: 0.8125rem; color: #7a7160; margin-bottom: 0.45rem; }
.requester img { width: 1.1rem; height: 1.1rem; border-radius: 50%; flex-shrink: 0; display: none; }
.requester .badge-tag { font-size: 0.75rem; border: 1px solid #7a7160; padding: 0.05rem 0.35rem; }
.requester .badge-icon { height: 0.9375rem; width: auto; display: block; }
.progress-row { display: flex; align-items: center; gap: 0.5rem; }
.bar-bg { flex: 1; height: 0.45rem; background: #e8dab8; border: 1px solid #1c1712; }
.bar-fill { height: 100%; background: #b6842c; }
.time { font-size: 0.8125rem; color: #7a7160; flex-shrink: 0; }
.perf { border-bottom: 1px dashed #1c1712; margin: 0.65rem 0 0.5rem; }
.setlist-label { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: #7a7160; margin-bottom: 0.4rem; }
.setlist { display: none; }
.setlist-row { display: flex; align-items: center; gap: 0.5rem; font-size: 0.9375rem; padding: 0.25rem 0; }
.setlist-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.setlist-badges { display: flex; align-items: center; gap: 0.2rem; flex-shrink: 0; }
.setlist-badge-icon { height: 0.9375rem; width: auto; display: block; }
.setlist-time { color: #7a7160; flex-shrink: 0; }
</style>
</head>
<body>
<div class="ticket">
<div class="tab"></div>
<div class="grommet"></div>
<div class="row-head">
<span class="status" id="status-el">Now Playing</span>
</div>
<div class="error-banner" id="error-banner"></div>
<div class="gap-banner" id="gap-banner"></div>
<div id="player-body">
<div class="now-playing">
<div class="cover" id="cover">
<span id="cover-fallback">♪</span>
<img id="cover-img" alt="">
</div>
<div class="info">
<div class="title" id="title-el">{{songTitle}}</div>
<div class="artist" id="artist-el">{{songArtist}}</div>
<div class="requester" id="requester-row">
<img id="requester-pic" alt="">
<span id="requester-name">{{requesterName}}</span>
<span id="requester-verified"></span>
<span id="requester-badges"></span>
</div>
<div class="progress-row" id="progress-row">
<div class="bar-bg">
<div class="bar-fill" style="width: {{progressPercent}}%"></div>
</div>
<div class="time" id="time-el" data-elapsed="{{elapsed}}" data-duration="{{duration}}">{{formattedElapsed}} / {{formattedDuration}}</div>
</div>
</div>
</div>
</div>
<div id="setlist-wrap">
<div class="perf" id="setlist-perf" style="display:none"></div>
<div class="setlist" id="setlist">
<div class="setlist-label" id="setlist-label">Up Next</div>
<div id="setlist-body"></div>
</div>
</div>
</div>
<script>
const isPlaying = "{{isPlaying}}" === "true";
const isPaused = "{{isPaused}}" === "true";
const isInGap = "{{isInGap}}" === "true";
const gapText = "{{gapText}}";
const errorText = "{{error}}";
const coverUrl = "{{songCoverArtUrl}}".trim();
const requesterPicture = "{{requesterPicture}}".trim();
const requesterBadges = "{{requesterBadges}}".trim();
const isRequesterVerified = "{{isRequesterVerified}}" === "true";
const BADGE_ICON_URLS = {
"Tako Verified Partner": "https://tako.id/images/badges/partnered-creator.png",
"Tako Verified Creator": "https://tako.id/images/badges/verified-creator.png",
"Rich Rich Club": "https://tako.id/images/badges/king.png",
"Charity": "https://tako.id/images/badges/charity.png",
"VTuber": "https://tako.id/images/badges/vtuber.png",
"Tako Team": "https://tako.id/images/badges/admin.png"
};
const titleEl = document.getElementById("title-el");
const artistEl = document.getElementById("artist-el");
const coverImg = document.getElementById("cover-img");
const coverFallback = document.getElementById("cover-fallback");
const statusEl = document.getElementById("status-el");
const errorBanner = document.getElementById("error-banner");
const gapBanner = document.getElementById("gap-banner");
const playerBody = document.getElementById("player-body");
const requesterRow = document.getElementById("requester-row");
const requesterPic = document.getElementById("requester-pic");
const requesterVerified = document.getElementById("requester-verified");
const requesterBadgesEl = document.getElementById("requester-badges");
const progressRow = document.getElementById("progress-row");
const setlistPerf = document.getElementById("setlist-perf");
const setlist = document.getElementById("setlist");
const setlistLabel = document.getElementById("setlist-label");
const setlistBody = document.getElementById("setlist-body");
const titleText = titleEl.textContent.trim();
const isIdle = !titleText || titleText === "{{" + "songTitle" + "}}";
if (errorText && !errorText.includes("{{")) {
errorBanner.textContent = "⚠ " + errorText;
errorBanner.style.display = "block";
}
if (isInGap) {
playerBody.style.display = "none";
gapBanner.textContent = gapText || "Menyiapkan lagu berikutnya...";
gapBanner.style.display = "block";
statusEl.textContent = "Gap";
} else if (isIdle) {
titleEl.textContent = "Belum ada lagu diputar";
titleEl.classList.add("idle");
artistEl.textContent = "Kirim hadiah untuk request lagu";
requesterRow.style.display = "none";
progressRow.style.display = "none";
coverFallback.style.display = "flex";
statusEl.textContent = "Idle";
} else {
statusEl.textContent = isPaused ? "Paused" : isPlaying ? "Now Playing" : "Buffering";
if (coverUrl && !coverUrl.includes("{{")) {
coverImg.src = coverUrl;
coverImg.style.display = "block";
coverFallback.style.display = "none";
coverImg.onerror = () => {
coverImg.style.display = "none";
coverFallback.style.display = "flex";
};
}
if (requesterPicture && !requesterPicture.includes("{{")) {
requesterPic.src = requesterPicture;
requesterPic.style.display = "block";
}
if (isRequesterVerified) requesterVerified.textContent = "✓";
if (requesterBadges) {
requesterBadges.split(",").filter(Boolean).forEach((name) => {
const iconUrl = BADGE_ICON_URLS[name];
if (iconUrl) {
const icon = document.createElement("img");
icon.className = "badge-icon";
icon.src = iconUrl;
icon.alt = name;
icon.title = name;
requesterBadgesEl.appendChild(icon);
} else {
const tag = document.createElement("span");
tag.className = "badge-tag";
tag.textContent = name;
requesterBadgesEl.appendChild(tag);
}
});
}
}
try {
const queueData = {{queue}};
if (Array.isArray(queueData) && queueData.length > 0) {
setlistPerf.style.display = "block";
setlist.style.display = "block";
setlistLabel.textContent = "Up Next (" + queueData.length + ")";
queueData.forEach((song, i) => {
const row = document.createElement("div");
row.className = "setlist-row";
const name = document.createElement("span");
name.className = "setlist-name";
name.textContent = (i + 1) + ". " + song.title + " — " + song.artist;
const badgesEl = document.createElement("div");
badgesEl.className = "setlist-badges";
(song.senderBadgeItems || []).forEach((badge) => {
if (!badge.url) return;
const icon = document.createElement("img");
icon.className = "setlist-badge-icon";
icon.src = badge.url;
icon.alt = badge.title || "";
icon.title = badge.title || "";
badgesEl.appendChild(icon);
});
const duration = document.createElement("span");
duration.className = "setlist-time";
duration.textContent = song.formattedDuration;
row.appendChild(name);
row.appendChild(badgesEl);
row.appendChild(duration);
setlistBody.appendChild(row);
});
}
} catch (e) {}
</script>
</body>
</html>
Informasi Tambahan yang Mungkin Muncul
- "⚠ Ini pesan uji coba": Muncul ketika overlay di tes atau preview.
- "⛔ Dikirim oleh Admin": Muncul ketika hadiah dikirim oleh tim/admin Tako.
Cara Mengimplementasikan/Membuat Custom Overlay
- Masuk Dashboard Kreator
- Cari Menu "Overlays" di Bagian Kiri
- Pilih Overlay (contoh: Alert)
- Di bagian "Tema", ubah ke "Custom HTML".
- Copy-paste kode yang udah kamu bikin ke kolom/textarea yang muncul.
- Cek Preview pada bagian atas.
Diperbarui pada: 04/08/2026
Terima kasih!
