Tahun Ajaran 2025/2026
Silakan unggah tautan video kesepakatan kelas Anda di sini.
Silakan isi form di bawah untuk mengirim data kesepakatan kelas Anda
📝 Form Tally.so: Klik di sini untuk mengisi form
Form akan terbuka di tab baru. Data otomatis tersimpan ke Google Sheets!
Jika form tidak muncul di atas:
Buka Form di Tab Baru✅ Form Siap Digunakan: Data otomatis tersimpan ke Google Sheets, mobile friendly, dan gratis!
📊 Galeri & Data: Data sudah tersinkron dengan Google Sheets! untuk melihat data terbaru.
Belum ada video yang diupload
Nama Kelas | Nama Guru | Tautan Video | Waktu Upload |
---|---|---|---|
Belum ada data yang tersimpan |
Video kesepakatan kelas telah berhasil disimpan dan ditambahkan ke galeri.
Nama Kelas | Nama Guru | Link Video | Waktu Upload
function doPost(e) {
try {
const sheet = SpreadsheetApp.getActiveSheet();
const data = JSON.parse(e.postData.contents);
// Tambah data ke baris baru
sheet.appendRow([
data.className,
data.teacherName,
data.videoLink,
new Date().toLocaleString('id-ID')
]);
return ContentService
.createTextOutput(JSON.stringify({success: true, message: 'Data berhasil disimpan'}))
.setMimeType(ContentService.MimeType.JSON);
} catch (error) {
return ContentService
.createTextOutput(JSON.stringify({success: false, error: error.toString()}))
.setMimeType(ContentService.MimeType.JSON);
}
}
// Function untuk test (opsional)
function doGet() {
return ContentService
.createTextOutput('Apps Script berjalan dengan baik!')
.setMimeType(ContentService.MimeType.TEXT);
}
💡 Tips: Jika masih bermasalah, coba buat Apps Script baru dari awal. Kadang ada cache issue yang perlu di-refresh.
Data dari Tally.so → Google Sheets → Website (Galeri & Tabel)
Butuh Google Apps Script untuk "jembatan" antara Sheets dan website.
Buka Google Sheets yang sudah terkoneksi Tally.so
Extensions → Apps Script
Copy-paste kode di sebelah →
Deploy sebagai Web App
Execute as: Me, Access: Anyone
Copy Web App URL
Ganti di kode website
function doGet(e) {
try {
const sheet = SpreadsheetApp.getActiveSheet();
const data = sheet.getDataRange().getValues();
// Skip header row if exists
const rows = data.length > 1 ? data.slice(1) : [];
// Filter out empty rows
const validRows = rows.filter(row =>
row[0] && row[1] && row[2] // Must have className, teacherName, videoLink
);
const result = validRows.map(row => ({
className: (row[0] || '').toString().trim(),
teacherName: (row[1] || '').toString().trim(),
videoLink: (row[2] || '').toString().trim(),
uploadTime: row[3] ? new Date(row[3]).toLocaleString('id-ID') : new Date().toLocaleString('id-ID')
}));
const output = ContentService
.createTextOutput(JSON.stringify({
success: true,
data: result,
count: result.length,
timestamp: new Date().toISOString()
}))
.setMimeType(ContentService.MimeType.JSON);
// Set CORS headers properly
output.setHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400'
});
return output;
} catch (error) {
const errorOutput = ContentService
.createTextOutput(JSON.stringify({
success: false,
error: error.toString(),
message: 'Error mengambil data dari Google Sheets',
timestamp: new Date().toISOString()
}))
.setMimeType(ContentService.MimeType.JSON);
// Set CORS headers for error response too
errorOutput.setHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization'
});
return errorOutput;
}
}
// Handle preflight OPTIONS requests
function doOptions(e) {
return ContentService
.createTextOutput('')
.setMimeType(ContentService.MimeType.TEXT)
.setHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400'
});
}
function doGet(e) {
try {
const sheet = SpreadsheetApp.getActiveSheet();
const data = sheet.getDataRange().getValues();
// Skip header row if exists
const rows = data.length > 1 ? data.slice(1) : [];
// Filter out empty rows
const validRows = rows.filter(row =>
row[0] && row[1] && row[2] // Must have className, teacherName, videoLink
);
const result = validRows.map(row => ({
className: (row[0] || '').toString().trim(),
teacherName: (row[1] || '').toString().trim(),
videoLink: (row[2] || '').toString().trim(),
uploadTime: row[3] ? new Date(row[3]).toLocaleString('id-ID') : new Date().toLocaleString('id-ID')
}));
const output = ContentService
.createTextOutput(JSON.stringify({
success: true,
data: result,
count: result.length,
timestamp: new Date().toISOString()
}))
.setMimeType(ContentService.MimeType.JSON);
// Set CORS headers properly
output.setHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400'
});
return output;
} catch (error) {
const errorOutput = ContentService
.createTextOutput(JSON.stringify({
success: false,
error: error.toString(),
message: 'Error mengambil data dari Google Sheets',
timestamp: new Date().toISOString()
}))
.setMimeType(ContentService.MimeType.JSON);
// Set CORS headers for error response too
errorOutput.setHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization'
});
return errorOutput;
}
}
// Handle preflight OPTIONS requests
function doOptions(e) {
return ContentService
.createTextOutput('')
.setMimeType(ContentService.MimeType.TEXT)
.setHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400'
});
}
✅ Copy kode di atas dan paste ke Google Apps Script, lalu deploy ulang sebagai Web App!
Setelah deploy Apps Script, ganti URL di kode website:
const APPS_SCRIPT_URL = 'YOUR_WEB_APP_URL_HERE';
Dengan URL Web App yang didapat dari Apps Script
⚠️ Catatan: Tanpa setup ini, galeri dan tabel akan kosong karena data hanya tersimpan di Google Sheets, tidak tersinkron ke website.
Buka tally.so → Sign up gratis dengan Google account
Klik "Create new form" → Pilih "Start from scratch"
Beri nama: "Dokumentasi Kesepakatan Kelas"
• Nama Kelas (Short text) - Required
• Nama Guru/Wali Kelas (Short text) - Required
• Link Video Kesepakatan (URL) - Required
Integrations → Google Sheets → Connect → Pilih/buat spreadsheet
Data akan otomatis masuk setiap ada submission!
Share → Embed → Copy embed code
Ganti YOUR_TALLY_FORM_ID_HERE
dengan ID form Anda
Dari URL embed Tally seperti ini:
https://tally.so/embed/w4jKQp
Ambil bagian w4jKQp dan ganti di kode HTML
💡 Pro Tips: Setelah setup, test form dengan submit 1 data. Cek Google Sheets untuk memastikan data masuk dengan benar!