Cara Membuat GuestPost di Blogger dengan Quilljs Editor
Di artikel kali ini sesuai dengan judulnya, saya akan memberikan Tutorial Cara Membuat Guestpost atau Kirim Artikel di Blogger dengan quilljs Editor HTML.

Melanjutkan artikel sebelumnya tentang Google Apps Script dengan judul Membuat Contact Form di Blogger, saya tertarik untuk sekalian membuat Form quilljs di Blogger. Berikut demo nya bisa dilihat disini: Kirim Artikel.
Tertarik untuk membuat GuestPosting di Blogger seperti Aurealisa? Simak caranya dibawah.
1. Siapkan Google Drive Folder
Sebelum kita mulai dengan kodenya, buat folder di Google Drive kalian untuk tempat menyimpan foto-foto dari postingan blog dari pengunjung.
- Buka Google Drive.
- Buat folder baru, misalnya "Blog Post Images".
- Catat ID folder ini. Kamu bisa menemukannya di URL folder (string panjang setelah /folders/). Contoh: https://drive.google.com/drive/folders/YOUR_FOLDER_ID.
2. Google Apps Script
Ini adalah bagian yang akan menerima data dari blog kalian dan mengirimkannya ke email kamu masing2.
1. Buka Google Apps Script.2. Klik "New project".
3. Hapus kode boilerplate yang ada (function myFunction() { ... }).
4. Salin dan tempel kode berikut ke dalam editor Apps Script:
const RECIPIENT_EMAIL = 'your.email@example.com'; // Ganti dengan alamat email Anda
const DRIVE_FOLDER_ID = 'YOUR_DRIVE_FOLDER_ID'; // Ganti dengan ID Folder Google Drive Anda
function doPost(e) {
const folder = DriveApp.getFolderById(DRIVE_FOLDER_ID);
if (!e.parameter.nama || !e.parameter.artikel) {
return createJsonResponse('error', 'Nama dan Artikel harus diisi.');
}
let nama = e.parameter.nama;
let artikelHTML = e.parameter.artikel; // Ini adalah HTML lengkap dari Quill
const tanggal = new Date();
// 1. Validasi panjang artikel dari teks biasa (Quill's Delta/HTML)
const tempDiv = HtmlService.createHtmlOutput(artikelHTML).getContent();
const textArtikel = tempDiv.replace(/(<([^>]+)>)/gi, ""); // Hapus semua tag HTML untuk hitungan kata
const kataArtikel = textArtikel.split(/\s+/).filter(word => word.length > 0).length;
if (kataArtikel < 500) {
return createJsonResponse('error', `Artikel harus minimal 500 kata. Saat ini ada ${kataArtikel} kata.`);
}
// 2. Tangani gambar yang disisipkan di editor Quill (berupa base64)
// Cari semua tag <img> yang src-nya adalah data:image/base64
const regex = /<img src="data:image\/[^;]+;base64,([^"]+)"\/?>/g;
let match;
let uploadedImageUrls = []; // Untuk melacak URL gambar yang diunggah
while ((match = regex.exec(artikelHTML)) !== null) {
const base64Data = match[1];
const mimeTypeMatch = match[0].match(/data:(image\/[^;]+);/);
const mimeType = mimeTypeMatch ? mimeTypeMatch[1] : 'image/png'; // Default ke png jika tidak ditemukan
try {
const decodedData = Utilities.base64Decode(base64Data);
const blob = Utilities.newBlob(decodedData, mimeType, `gambar_${Date.now()}_${uploadedImageUrls.length + 1}.${mimeType.split('/')[1]}`);
const file = folder.createFile(blob);
const fileUrl = file.getUrl();
uploadedImageUrls.push(fileUrl); // Simpan URL untuk referensi
// Ganti string base64 asli di HTML dengan URL Drive yang baru
artikelHTML = artikelHTML.replace(match[0], `<img src="${fileUrl}" style="max-width:100%; height:auto;" />`);
// Tambahkan style dasar agar gambar tidak terlalu besar di email/tampilan
} catch (error) {
Logger.log('Error uploading embedded image: ' + error.message);
// Jika ada error upload gambar, kita bisa log dan melanjutkan tanpa gambar itu,
// atau mengembalikan error ke pengguna. Untuk saat ini, kita log dan coba lanjutkan.
// Opsional: ganti gambar yang gagal dengan placeholder teks atau hapus.
artikelHTML = artikelHTML.replace(match[0], `[Gambar Gagal Diunggah]`);
}
}
// Siapkan isi email dalam format HTML
const subject = `Postingan Blog Baru dari ${nama}`;
const htmlBody = `
<p>Halo Admin,</p>
<p>Anda menerima postingan blog baru:</p>
<p><b>Nama Penulis:</b> ${nama}<br>
<b>Tanggal:</b> ${tanggal.toLocaleString()}</p>
<h3>Isi Artikel:</h3>
<div style="border: 1px solid #eee; padding: 15px; background-color: #f9f9f9; word-wrap: break-word; overflow-wrap: break-word;">
${artikelHTML} </div>
<br>
<p><b>Gambar yang diunggah:</b></p>
<ul>
${uploadedImageUrls.length > 0 ? uploadedImageUrls.map(url => `<li><a href="${url}">${url}</a></li>`).join('') : '<li>Tidak ada gambar diunggah melalui editor.</li>'}
</ul>
<p>Silakan tinjau postingan ini.</p>
`;
try {
MailApp.sendEmail({
to: RECIPIENT_EMAIL,
subject: subject,
htmlBody: htmlBody
});
return createJsonResponse('success', 'Postingan Anda berhasil dikirim! Terima kasih.');
} catch (error) {
Logger.log('Error sending email: ' + error.message);
return createJsonResponse('error', 'Terjadi kesalahan saat mengirim postingan: ' + error.message);
}
}
function createJsonResponse(status, message) {
return ContentService
.createTextOutput(JSON.stringify({ status: status, message: message }))
.setMimeType(ContentService.MimeType.JSON);
}
5. Penting:
- Ganti 'YOUR_DRIVE_FOLDER_ID' dengan ID folder Google Drive yang kamu buat di langkah 1 nomor 3.
- Ganti 'your.email@example.com' dengan alamat email kamu sendiri.
6. Deploy sebagai Aplikasi Web:
- Klik Deploy > New deployment. Pilih Web app sebagai tipe deployment.
- Description: "Blog Post Sender" (atau nama lain yang Anda inginkan).
- Execute as: Me (email Anda).
- Who has access: Anyone. Ini penting agar formulir dari blog kalian bisa mengirim data tanpa memerlukan login Google.
- Klik Deploy.
- Google akan meminta kamu untuk memberikan izin. Ikuti langkah-langkah Review permissions dan Allow akses ke Google Drive dan Gmail.
- Setelah berhasil di-deploy, kamu akan mendapatkan URL aplikasi web. Salin URL ini. Ini adalah URL yang akan kamu gunakan di kode JavaScript dibawah nanti.
3. HTML, CSS dan JavaScript
Sekarang, kita akan mengintegrasikan Quill.js ke dalam edit HTML blogger kalian
<div class="blog-post-form-container">
<h2>Kirim Postingan Anda</h2>
<form id="blogPostForm">
<div class="form-group">
<label for="nama">Nama Anda:</label>
<input type="text" id="nama" name="nama" required>
</div>
<div class="form-group">
<label for="artikel">Isi Artikel (minimal 500 kata):</label>
<div id="editor-container" style="height: 300px;"></div>
<input type="hidden" id="artikel" name="artikel">
<div id="wordCount" class="word-count">0 kata</div>
</div>
<button type="submit" id="submitButton">Kirim Artikel</button>
</form>
<div id="responseMessage" class="response-message" style="display: none;"></div>
</div>
- Untuk Css nya seperti ini
/* Styling Formulir Kirim Artikel */
.blog-post-form-container {
max-width: 700px;
margin: 20px auto;
padding: 25px;
border: 1px solid #e0e0e0;
border-radius: 8px;
background-color: #fcfcfc;
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
}
.blog-post-form-container h2 {
text-align: center;
color: #333;
margin-bottom: 25px;
}
.form-group {
margin-bottom: 18px;
}
.form-group label {
display: block;
margin-bottom: 7px;
font-weight: bold;
color: #555;
}
.form-group input[type="text"] {
width: calc(100% - 20px);
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
box-sizing: border-box;
font-size: 1em;
}
/* Styling untuk Quill.js editor */
#editor-container {
border: 1px solid #ccc;
border-radius: 5px;
font-size: 1em;
background-color: white;
}
.ql-toolbar {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
border-bottom: 1px solid #ccc; /* Pemisah toolbar dan editor */
}
.ql-container {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
.word-count {
font-size: 0.85em;
color: #666;
margin-top: 5px;
text-align: right;
}
button[type="submit"] {
display: block;
width: 100%;
padding: 12px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
font-size: 1.1em;
cursor: pointer;
transition: background-color 0.3s ease;
}
button[type="submit"]:hover {
background-color: #0056b3;
}
button[type="submit"]:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
.response-message {
padding: 15px;
margin-top: 20px;
border-radius: 5px;
font-weight: bold;
text-align: center;
}
.response-message.success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.response-message.error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
- Tambahkan javascript seperti ini
document.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('blogPostForm');
const submitButton = document.getElementById('submitButton');
const responseMessageDiv = document.getElementById('responseMessage');
const artikelHiddenInput = document.getElementById('artikel');
const wordCountDiv = document.getElementById('wordCount');
// GANTI DENGAN URL Aplikasi Web Apps Script kamu yang sudah di-deploy
const appsScriptUrl = 'https://script.google.com/macros/s/xxxxx/exec'; // <--- GANTI DI SINI
// Inisialisasi Quill editor
const quill = new Quill('#editor-container', {
theme: 'snow',
modules: {
toolbar: [
[{ 'header': [1, 2, 3, false] }],
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'indent': '-1'}, { 'indent': '+1' }],
['link', 'image'], // Tombol 'image' kembali di sini!
[{ 'align': [] }],
['clean']
]
// Quill secara otomatis akan mengelola penyisipan gambar base64 ke dalam editor.
// Tidak perlu handler image tambahan di frontend.
}
});
const updateWordCount = () => {
const text = quill.getText(); // Mendapatkan teks biasa dari editor
const words = text.split(/\s+/).filter(word => word.length > 0);
wordCountDiv.textContent = `${words.length} kata`;
if (words.length < 500) {
wordCountDiv.style.color = 'red';
} else {
wordCountDiv.style.color = 'green';
}
};
quill.on('text-change', updateWordCount);
updateWordCount();
form.addEventListener('submit', async (event) => {
event.preventDefault();
responseMessageDiv.style.display = 'none';
responseMessageDiv.className = 'response-message';
submitButton.disabled = true;
submitButton.textContent = 'Mengirim...';
// Ambil konten HTML dari Quill editor dan masukkan ke input hidden
artikelHiddenInput.value = quill.root.innerHTML;
// Validasi panjang artikel di frontend
const textContent = quill.getText(); // Gunakan teks biasa dari editor
const words = textContent.split(/\s+/).filter(word => word.length > 0);
if (words.length < 500) {
responseMessageDiv.textContent = `Artikel Anda harus minimal 500 kata. Saat ini ada ${words.length} kata.`;
responseMessageDiv.classList.add('error');
responseMessageDiv.style.display = 'block';
submitButton.disabled = false;
submitButton.textContent = 'Kirim Artikel';
return;
}
const formData = new FormData(form);
const params = new URLSearchParams();
// Semua data yang ada di formData (nama, dan artikel HTML) akan ditambahkan
for (const [key, value] of formData.entries()) {
params.append(key, value);
}
await sendData(params);
});
async function sendData(params) {
try {
const response = await fetch(appsScriptUrl, {
method: 'POST',
body: params
});
const data = await response.json();
if (data.status === 'success') {
responseMessageDiv.textContent = data.message;
responseMessageDiv.classList.add('success');
form.reset();
quill.setText(''); // Kosongkan editor Quill
updateWordCount();
} else {
responseMessageDiv.textContent = data.message || 'Pengiriman gagal. Mohon coba lagi.';
responseMessageDiv.classList.add('error');
}
} catch (error) {
console.error('Error saat mengirim formulir:', error);
responseMessageDiv.textContent = 'Terjadi kesalahan jaringan. Mohon coba lagi.';
responseMessageDiv.classList.add('error');
} finally {
responseMessageDiv.style.display = 'block';
submitButton.disabled = false;
submitButton.textContent = 'Kirim Artikel';
}
}
});
- Link CSS dan JS Quill.js:
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
Ini harus ditambahkan di bagian <head> atau tepat sebelum tag </body> penutup.
4. Publikasikan
Publikasikan postingan blog kamu dan lihat hasilnya.
Sekarang kamu punya Guest Posting di halaman sendiri, semoga bermanfaat ya :)
Post a Comment