Add Google Sheets webhook, email to Cgabijendra@gmail.com, WhatsApp button

- Every inquiry fires 3 simultaneous destinations: Google Sheet, email, Kondesk
- Email to Cgabijendra@gmail.com with HTML template + reply-to set to the lead
- GOOGLE_SHEET_WEBHOOK env var (set once Google Apps Script is deployed)
- WhatsApp floating button bottom-right, links to +61 405 580 047

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
King Omar 2026-07-10 13:41:22 +10:00
parent 29cfa0b9ac
commit 91b7a948fd
4 changed files with 193 additions and 60 deletions

89
google-apps-script.js Normal file
View file

@ -0,0 +1,89 @@
// ============================================================
// Careers Gateway — Google Apps Script Webhook
// Paste this into Extensions → Apps Script in your Google Sheet
// Deploy as: Web App → Execute as: Me → Access: Anyone
// ============================================================
const NOTIFY_EMAIL = 'Cgabijendra@gmail.com';
const SHEET_NAME = 'Inquiries';
function doPost(e) {
try {
var data = JSON.parse(e.postData.contents);
appendToSheet(data);
sendNotificationEmail(data);
return ok();
} catch (err) {
return ContentService
.createTextOutput(JSON.stringify({ success: false, error: err.message }))
.setMimeType(ContentService.MimeType.JSON);
}
}
// Allow CORS preflight
function doGet(e) {
return ok();
}
function appendToSheet(data) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(SHEET_NAME);
if (!sheet) {
sheet = ss.insertSheet(SHEET_NAME);
sheet.appendRow([
'Date (AEST)', 'Full Name', 'Email', 'Phone',
'Service', 'Course Name', 'CRICOS Code', 'Institution', 'Message', 'Source'
]);
// Bold the header row
sheet.getRange(1, 1, 1, 10).setFontWeight('bold').setBackground('#1a2744').setFontColor('#ffffff');
sheet.setFrozenRows(1);
}
sheet.appendRow([
data.submittedAt || new Date().toLocaleString('en-AU', { timeZone: 'Australia/Sydney' }),
data.fullName || '',
data.email || '',
data.phone || '',
data.service || '',
data.courseName || '',
data.cricosCode || '',
data.provider || '',
data.message || '',
data.source || 'careersgateway.com.au',
]);
}
function sendNotificationEmail(data) {
var subject = '🔔 New Inquiry: ' + (data.fullName || 'Unknown') + ' — ' + (data.service || 'General');
var body =
'<div style="font-family:Arial,sans-serif;color:#1a2744;max-width:560px">' +
'<div style="background:#1a5bb8;padding:18px 24px;border-radius:6px 6px 0 0">' +
'<h2 style="color:#fff;margin:0;font-size:1rem">New Inquiry — Careers Gateway Portal</h2>' +
'</div>' +
'<table style="width:100%;border-collapse:collapse;border:1px solid #e8f0fe;border-top:none">' +
row('Name', data.fullName) +
row('Email', '<a href="mailto:' + data.email + '">' + data.email + '</a>') +
row('Phone', data.phone || '—') +
row('Service', data.service || '—') +
row('Course', data.courseName ? data.courseName + (data.cricosCode ? ' (CRICOS: ' + data.cricosCode + ')' : '') : '—') +
row('Institution', data.provider || '—') +
row('Message', data.message || '—') +
row('Submitted', data.submittedAt || new Date().toLocaleString('en-AU')) +
'</table>' +
'<div style="padding:16px;text-align:center">' +
'<a href="mailto:' + data.email + '" style="background:#1a5bb8;color:#fff;padding:10px 22px;border-radius:6px;text-decoration:none;font-weight:bold">Reply to ' + (data.fullName||'').split(' ')[0] + '</a>' +
'</div></div>';
GmailApp.sendEmail(NOTIFY_EMAIL, subject, '', { htmlBody: body, replyTo: data.email });
}
function row(label, value) {
return '<tr><td style="padding:9px 16px;color:#64748b;font-size:.88rem;background:#f8faff;width:120px">' +
label + '</td><td style="padding:9px 16px;font-size:.9rem">' + (value || '') + '</td></tr>';
}
function ok() {
return ContentService
.createTextOutput(JSON.stringify({ success: true }))
.setMimeType(ContentService.MimeType.JSON);
}

View file

@ -1,76 +1,109 @@
// Konpare/Kondesk lead push
// The Konpare API key is used for their widget embed (OSHC comparison)
// and for posting lead data when a course inquiry is submitted.
const NOTIFY_EMAIL = 'Cgabijendra@gmail.com';
async function pushLeadToKondesk(env, lead) {
const payload = {
api_key: env.KONPARE_KEY,
lead: {
full_name: lead.fullName,
email: lead.email,
phone: lead.phone || '',
service: lead.service || 'Course Inquiry',
course_code: lead.cricosCode || '',
course_name: lead.courseName || '',
provider: lead.provider || '',
message: lead.message || '',
source: 'careers.bored.investments',
}
};
// Try Konpare lead submission endpoint
const endpoints = [
'https://app.konpare.online/api/leads',
'https://app.konpare.online/api/v1/leads',
'https://app.kondesk.com/api/leads',
];
for (const url of endpoints) {
try {
const res = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${env.KONPARE_KEY}`,
'x-api-key': env.KONPARE_KEY,
},
body: JSON.stringify(payload),
});
if (res.ok) return { success: true, endpoint: url };
} catch (_) {}
}
// Fallback: email notification
await sendEmailFallback(env, lead);
return { success: false, fallback: 'email' };
// Fire all three in parallel — Google Sheet, email, Kondesk
await Promise.allSettled([
pushToGoogleSheet(env, lead),
sendEmail(env, lead),
pushToKondesk(env, lead),
]);
return { success: true };
}
async function sendEmailFallback(env, lead) {
// Cloudflare Email Routing send — uses MailChannels via Workers
const emailBody = `
New Lead from Careers Gateway Portal
async function pushToGoogleSheet(env, lead) {
const url = env.GOOGLE_SHEET_WEBHOOK;
if (!url) return;
await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
fullName: lead.fullName,
email: lead.email,
phone: lead.phone || '',
service: lead.service || '',
courseName: lead.courseName || '',
cricosCode: lead.cricosCode || '',
provider: lead.provider || '',
message: lead.message || '',
source: 'careersgateway.com.au',
submittedAt: new Date().toLocaleString('en-AU', { timeZone: 'Australia/Sydney' }),
}),
});
}
Name: ${lead.fullName}
Email: ${lead.email}
Phone: ${lead.phone || 'N/A'}
Service: ${lead.service || 'N/A'}
Course: ${lead.courseName || 'N/A'} (${lead.cricosCode || 'N/A'})
Provider: ${lead.provider || 'N/A'}
Message: ${lead.message || 'N/A'}
Submitted: ${new Date().toLocaleString('en-AU', { timeZone: 'Australia/Sydney' })}
`.trim();
async function sendEmail(env, lead) {
const dt = new Date().toLocaleString('en-AU', { timeZone: 'Australia/Sydney', dateStyle: 'full', timeStyle: 'short' });
const html = `
<!DOCTYPE html><html><body style="font-family:Arial,sans-serif;color:#1a2744;max-width:600px;margin:0 auto">
<div style="background:linear-gradient(135deg,#1a2744,#1a5bb8);padding:24px 28px;border-radius:8px 8px 0 0">
<img src="https://careersgateway.com.au/wp-content/uploads/2025/06/cropped-Screenshot-2025-06-15-at-1.59.23_PM-300x159-removebg-preview-192x192.png" style="height:36px;filter:brightness(0) invert(1)">
<h2 style="color:#fff;margin:8px 0 0;font-size:1.1rem">New Inquiry Careers Gateway Portal</h2>
</div>
<div style="background:#f0f6ff;padding:24px 28px;border-radius:0 0 8px 8px">
<table style="width:100%;border-collapse:collapse">
<tr><td style="padding:8px 0;color:#64748b;width:130px;font-size:.9rem">Name</td><td style="padding:8px 0;font-weight:700">${esc(lead.fullName)}</td></tr>
<tr style="background:#fff"><td style="padding:8px 12px;color:#64748b;font-size:.9rem">Email</td><td style="padding:8px 12px"><a href="mailto:${esc(lead.email)}">${esc(lead.email)}</a></td></tr>
<tr><td style="padding:8px 0;color:#64748b;font-size:.9rem">Phone</td><td style="padding:8px 0"><a href="tel:${esc(lead.phone||'')}">${esc(lead.phone||'')}</a></td></tr>
<tr style="background:#fff"><td style="padding:8px 12px;color:#64748b;font-size:.9rem">Service</td><td style="padding:8px 12px">${esc(lead.service||'')}</td></tr>
${lead.courseName ? `<tr><td style="padding:8px 0;color:#64748b;font-size:.9rem">Course</td><td style="padding:8px 0">${esc(lead.courseName)}${lead.cricosCode ? ` <span style="color:#1a5bb8;font-size:.85rem">(CRICOS: ${esc(lead.cricosCode)})</span>` : ''}</td></tr>` : ''}
${lead.provider ? `<tr style="background:#fff"><td style="padding:8px 12px;color:#64748b;font-size:.9rem">Institution</td><td style="padding:8px 12px">${esc(lead.provider)}</td></tr>` : ''}
${lead.message ? `<tr><td style="padding:8px 0;color:#64748b;font-size:.9rem;vertical-align:top">Message</td><td style="padding:8px 0">${esc(lead.message)}</td></tr>` : ''}
<tr style="background:#fff"><td style="padding:8px 12px;color:#64748b;font-size:.9rem">Submitted</td><td style="padding:8px 12px;font-size:.85rem">${dt}</td></tr>
</table>
<div style="margin-top:20px;text-align:center">
<a href="mailto:${esc(lead.email)}" style="background:#1a5bb8;color:#fff;padding:11px 24px;border-radius:6px;text-decoration:none;font-weight:700;font-size:.9rem">Reply to ${esc(lead.fullName.split(' ')[0])}</a>
</div>
</div>
</body></html>`;
// MailChannels (works on Cloudflare Workers for domains with SPF set)
try {
await fetch('https://api.mailchannels.net/tx/v1/send', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
personalizations: [{ to: [{ email: env.CONTACT_EMAIL, name: 'Careers Gateway' }] }],
personalizations: [{ to: [{ email: NOTIFY_EMAIL, name: 'Bijendra — Careers Gateway' }] }],
from: { email: 'noreply@careersgateway.com.au', name: 'Careers Gateway Portal' },
subject: `New Lead: ${lead.fullName}${lead.service || 'Course Inquiry'}`,
content: [{ type: 'text/plain', value: emailBody }],
reply_to: { email: lead.email, name: lead.fullName },
subject: `New Inquiry: ${lead.fullName}${lead.service || 'General'}`,
content: [
{ type: 'text/plain', value: `New inquiry from ${lead.fullName} (${lead.email} / ${lead.phone})\n\nService: ${lead.service}\nCourse: ${lead.courseName||'N/A'}\nMessage: ${lead.message||'N/A'}` },
{ type: 'text/html', value: html },
],
}),
});
} catch (_) {}
}
function esc(str) {
return String(str || '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}
async function pushToKondesk(env, lead) {
const endpoints = [
'https://app.konpare.online/api/leads',
'https://app.konpare.online/api/v1/leads',
'https://app.kondesk.com/api/leads',
];
const payload = {
api_key: env.KONPARE_KEY,
lead: {
full_name: lead.fullName, email: lead.email, phone: lead.phone||'',
service: lead.service||'Course Inquiry', course_code: lead.cricosCode||'',
course_name: lead.courseName||'', provider: lead.provider||'',
message: lead.message||'', source: 'careersgateway.com.au',
}
};
for (const url of endpoints) {
try {
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${env.KONPARE_KEY}`, 'x-api-key': env.KONPARE_KEY },
body: JSON.stringify(payload),
});
if (res.ok) return;
} catch (_) {}
}
}
export { pushLeadToKondesk };

View file

@ -203,6 +203,16 @@ ${extraHead}
</div>
</nav>
${body}
<!-- WhatsApp floating button -->
<a href="https://wa.me/61405580047?text=Hi%20Careers%20Gateway%2C%20I%27d%20like%20to%20enquire%20about%20your%20services."
target="_blank" rel="noopener"
aria-label="Chat on WhatsApp"
style="position:fixed;bottom:24px;right:24px;z-index:999;width:58px;height:58px;background:#25D366;border-radius:50%;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 16px rgba(37,211,102,.45);transition:.2s"
onmouseover="this.style.transform='scale(1.1)'" onmouseout="this.style.transform='scale(1)'">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="30" height="30" fill="#fff">
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
</svg>
</a>
<footer>
<div class="footer-inner">
<div class="footer-grid">

View file

@ -23,5 +23,6 @@ id = "5b40ceec3c6446409351805028e63453"
[vars]
SITE_NAME = "Careers Gateway"
CONTACT_EMAIL = "info@careersgateway.com.au"
CONTACT_EMAIL = "Cgabijendra@gmail.com"
KONPARE_KEY = "ViL_0iMMCdHrXNoEQKFm4P5092ISFcYzEyLmf5MFBKds7Hw5BmORaXu3oGsMB5Lk"
GOOGLE_SHEET_WEBHOOK = ""