🎓 Download your Course Certificate

Complete every lesson of the course (reach 100% in the reader), then sign in with the same Google account / email in your One-Stop Form membership. You'll accept a short honor-code pledge, and the certificate is issued only to members who have genuinely completed the course.

`; const w = window.open('', '_blank', 'width=1300,height=900,scrollbars=yes,resizable=yes'); if (!w){ alert('Please allow pop-ups to view/print your certificate.'); return; } w.opener = null; w.document.open(); w.document.write(html); w.document.close(); } function fitLogos(scope){ (scope || document).querySelectorAll('.logo-grid').forEach(grid => { const n = grid.querySelectorAll('img').length || 1; const gap = parseFloat(getComputedStyle(grid).gap) || 12; const w = grid.clientWidth || 600; const perW = (w - gap*(n-1)) / n; const h = Math.max(16, Math.min(52, Math.floor(perW * 0.55))); grid.style.setProperty('--logo-h', h + 'px'); }); } function scaleInlinePreview(){ const box = document.getElementById('certPreview'); const scaler = document.getElementById('certScale'); if (!box || !scaler) return; const avail = box.clientWidth - 24; const scale = Math.min(1, avail / 1123); scaler.style.transform = `scale(${scale})`; scaler.style.height = (794 * scale) + 'px'; } function showInlineCertificate(cert){ const el = document.getElementById('certificateResult'); el.innerHTML = infoBoxHTML() + '
✅ Course completion verified. ' + 'Your certificate is ready below. Open the print-ready version to save it as a PDF.
' + '
' + '' + '
' + '
' + certPageHTML(cert) + '
'; const finish = () => { fitLogos(el); scaleInlinePreview(); }; const imgs = [...el.querySelectorAll('img')].filter(im => !im.complete || im.naturalWidth === 0); if (imgs.length){ Promise.all(imgs.map(im => new Promise(r => { im.onload = im.onerror = () => r(); }))).then(finish); } else { finish(); } window.addEventListener('resize', scaleInlinePreview); const printBtn = document.getElementById('openPrintBtn'); if (printBtn) printBtn.addEventListener('click', () => openCertificatesInNewTab([cert], true)); } /* ===== Sign-in + verify flow ===== */ function hideSignin(){ const r = document.getElementById('signinRow'); if (r) r.style.display = 'none'; } async function verifyAndGenerate(credential, pledge){ setStatus('info', pledge ? '⏳ Issuing your certificate…' : '⏳ Checking your course completion…'); try{ const apiUrl = await window.CCApiHub.resolve(API_VARIABLE, { showClock: false }); const body = new URLSearchParams({ action: "certificate", googleCredential: credential || "", course: COURSE_SLUG, courseTitle: courseTitle(), pledge: pledge ? "yes" : "", origin: location.origin, pageUrl: location.href, userAgent: navigator.userAgent }); const ac = new AbortController(); const to = setTimeout(() => ac.abort(), 15000); const res = await fetch(apiUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", Accept: "application/json" }, body: body, signal: ac.signal }); clearTimeout(to); const data = await res.json().catch(() => ({})); if (!res.ok || (data && data.error)) throw new Error((data && data.error) || ("HTTP " + res.status)); if (data.eligible && data.certificate){ showInlineCertificate(normalizeCert(data.certificate)); return; } // Member + course complete, but the honor-code pledge must be accepted // before we issue the certificate (server withholds it until pledge=yes). if (data.eligible && data.needPledge){ showPledgeGate(credential, data); return; } if (data.reason === "course_incomplete"){ setStatus('info', 'Almost there! Finish every lesson (reach 100%) in the course reader to unlock your certificate.
' + `Back to the course`); return; } if (data.reason === "onestop_incomplete"){ setStatus('info', '🎉 You finished the course! To download your certificate you first need to be a member — ' + 'complete the One-Stop Form with this same email.
' + `Complete the One-Stop Form`); return; } setStatus('error', 'We couldn\'t verify a completed course for this account. ' + `Back to the course`); }catch(err){ setStatus('error', ccUserError(err && err.name === "AbortError" ? "TIMEOUT" : "RUNTIME", err) + ' — we could not verify your course completion right now.'); } } /* ===== Honor-code pledge (hard gate before download) ===== */ function showPledgeGate(credential, data){ const el = document.getElementById('certificateResult'); el.innerHTML = infoBoxHTML() + '
🎉 You finished the course' + ', and you\'re a verified member. One last step before your certificate.
' + '
' + '

Code Crunch Honor Code

' + '

I confirm that I personally worked through ' + esc(courseTitle()) + ' ' + 'and genuinely completed it. I did this work ' + 'honestly and on my own merit, and I did not misrepresent my progress. I understand this certificate ' + 'carries my name and reflects my genuine effort — and that Code Crunch runs on trust.

' + '' + '
' + '' + '
' + '
'; const chk = document.getElementById('pledgeAgree'); const btn = document.getElementById('pledgeBtn'); if (chk && btn){ chk.addEventListener('change', () => { btn.disabled = !chk.checked; }); btn.addEventListener('click', () => { if (!chk.checked) return; btn.disabled = true; verifyAndGenerate(credential, true); }); } } function onCredential(response){ const credential = response && response.credential; if (!credential){ setStatus('error', ccUserError("SIGN_IN_FAILED")); return; } hideSignin(); verifyAndGenerate(credential, false); } function initGsi(){ if (!(window.google && google.accounts && google.accounts.id)){ return setTimeout(initGsi, 250); } google.accounts.id.initialize({ client_id: GIS_CLIENT_ID, callback: onCredential, auto_select: false }); const host = document.getElementById('gsiButton'); if (host) google.accounts.id.renderButton(host, { type: "standard", size: "large", theme: "filled_blue", text: "signin_with", shape: "pill", logo_alignment: "left" }); } document.addEventListener('DOMContentLoaded', () => { document.getElementById('certificateResult').innerHTML = infoBoxHTML() + 'Sign in with Google above to verify your course completion and download your certificate…'; if (!COURSE_SLUG){ hideSignin(); setStatus('error', 'This page needs a course. Open it from your course\'s progress panel, ' + 'or add ?course=c1 to the URL.'); return; } initGsi(); });