Aktivasi Profil Usaha Baru / Edit Kartu
Paket Basic sudah dilengkapi Pesan Cepat Bintang 1–3 & Komentar Cepat Bintang 4–5. Paket Pro membuka Logo, Free WiFi QR, Menu & Sosmed.
A. Buat QR / Link ID Kartu Renggang (Stok Cetak)
Pre-PrintedGunakan menu ini untuk membuat QR Code Renggang & Cantik yang bisa dicetak massal ke kartu PVC/akrilik sebelum dijual.
B. Hubungkan Link Aktivasi Final ke ID Kartu
Terkunci AdminMasukkan Link Aktivasi Final untuk dipasangkan ke ID Kartu tertentu. Data otomatis tersimpan ke Google Sheets & Backup.
🛡️ Cara Agar QR ID Renggang (/r?id=TB-003) Jalan di Semua HP:
Karena ekor panjang &gs=... sudah kita hapus supaya QR Code cantik & renggang, cukup klik tombol "📦 Unduh Backup cards.json (Public)" di Tab 3 lalu simpan ke folder public/cards.json saat deploy ke Netlify!
📋 Daftar Kartu Aktif & Double-Backup Server
Semua kartu yang sudah aktif terkunci aman (hanya Admin yang dapat mengubah identitasnya).
⚙️ Pengaturan Sistem, PIN Keamanan & Database
Wajib dimasukkan saat membuka halaman Admin.
Kosongkan untuk otomatis mengikuti domain saat ini.
Tujuan WA saat klien ingin upgrade ke Paket Pro.
🔍 Pencarian Autocomplete Nama Toko ala Productmate (Opsional & Ringan)
LAZY-LOAD (0 KB BEBAN)📊 Database Utama (Real-Time Lintas HP & Pencari Place ID): Google Sheets
DOUBLE-BACKUP AKTIF
URL Google Sheets ini berfungsi ganda: (1) Menyimpan data kartu secara real-time dan (2) Mengubah link Maps menjadi Place ID ChIJ... agar di iPhone langsung membuka form Beri Ulasan!
📖 Klik di sini untuk melihat Panduan & Kode Copy-Paste Google Sheets Script
- Buka Google Drive → Buat file Google Sheets baru → Klik Extensions (Ekstensi) → Apps Script.
- Salin & Tempel kode di bawah ini, lalu klik Deploy → New deployment (Web App, Access: Anyone):
function doGet(e) {
var action = (e && e.parameter && e.parameter.action) ? e.parameter.action : 'get';
if (action === 'findPlace') {
var q = e.parameter.q || '';
var placeId = '', resolvedUrl = '', nameFound = '';
try {
var searchName = q;
if (q.indexOf('http') === 0) {
var resp = UrlFetchApp.fetch(q, { followRedirects: true, muteHttpExceptions: true });
var html = resp.getContentText();
var mChij = html.match(/(ChIJ[0-9a-zA-Z_-]{15,35})/);
if (mChij) placeId = mChij[1];
var mHex = html.match(/0x[0-9a-fA-F]+:0x[0-9a-fA-F]+/);
if (mHex) resolvedUrl = mHex[0];
var mPlace = html.match(/\/maps\/place\/([^\/@"\?]+)/i);
if (mPlace) searchName = decodeURIComponent(mPlace[1].replace(/\+/g, ' '));
}
if (!placeId && searchName) {
var geo = Maps.newGeocoder().geocode(searchName);
if (geo && geo.results && geo.results.length > 0) {
placeId = geo.results[0].place_id || '';
nameFound = geo.results[0].formatted_address || '';
}
}
} catch (err) {}
return ContentService.createTextOutput(JSON.stringify({ ok: true, placeId: placeId, hexId: resolvedUrl, address: nameFound })).setMimeType(ContentService.MimeType.JSON);
}
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var id = (e && e.parameter && e.parameter.id) ? e.parameter.id : '';
var rows = sheet.getDataRange().getValues();
if (action === 'get' && id) {
for (var i = 1; i < rows.length; i++) {
if (String(rows[i][0]) === String(id)) {
return ContentService.createTextOutput(JSON.stringify({ found: true, data: JSON.parse(rows[i][2]) })).setMimeType(ContentService.MimeType.JSON);
}
}
return ContentService.createTextOutput(JSON.stringify({ found: false })).setMimeType(ContentService.MimeType.JSON);
}
return ContentService.createTextOutput(JSON.stringify({ ok: true })).setMimeType(ContentService.MimeType.JSON);
}
function doPost(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
if (sheet.getLastRow() === 0) sheet.appendRow(['CardID', 'ShopName', 'JSONData', 'FinalLink', 'UpdatedAt']);
var body = JSON.parse(e.postData.contents);
var id = String(body.cardId);
var rows = sheet.getDataRange().getValues();
for (var i = 1; i < rows.length; i++) {
if (String(rows[i][0]) === id) {
sheet.getRange(i + 1, 2, 1, 4).setValues([[body.shopName || '', JSON.stringify(body), body.finalLink || '', new Date().toISOString()]]);
return ContentService.createTextOutput(JSON.stringify({ saved: true })).setMimeType(ContentService.MimeType.JSON);
}
}
sheet.appendRow([id, body.shopName || '', JSON.stringify(body), body.finalLink || '', new Date().toISOString()]);
return ContentService.createTextOutput(JSON.stringify({ saved: true })).setMimeType(ContentService.MimeType.JSON);
}