Join the Insider List
Early access, parent-only perks, and new features first.
What Parents Get
Fast, age-fit help for everyday moments — with clear words you can use tonight.
😴
Sleep Made
Simpler
Bedtime scripts that actually work.
🌅
Calmer
Mornings
5-line plans you can read aloud.
🤝
Fewer Power
Struggles
Age-fit boundaries in a kind tone.
💬
Confident
Parenting
Clear words for tough moments.
For Every Age 0–17
0–3- Bedtime refusal
- Separation tears
- First boundaries
4–7- Morning routine
- Sibling fights
- Big feelings
8–12- Homework stall
- Screen limits
- Friendship bumps
13–17- Curfews
- Social media
- School stress
See a Script
Real, age-fit examples you can use tonight.
One-liner“It’s time for sleep. I’ll tuck you in and stay for two songs, then lights off.”
5-Line Script
- “I see you want more play. It’s hard to stop when you’re having fun.”
- “Bedtime keeps your body strong. We do the same steps every night.”
- “Pick one: spaceship pajamas or dinos?”
- “Two songs, then lights off. I’ll check on you after.”
- “You chose dinos. Climb in—I’m right here.”
One-liner“Pause. Hands to self. Tell me what you each wanted—one at a time.”
5-Line Script
- “I’m stopping this. Hands to self—now.”
- “You go first. What did you want?”
- “You next. What did you want?”
- “We have two options: timer to share or trade items.”
- “You chose timer. I’ll set five minutes and stay nearby.”
One-liner“I want you safe. Curfew is 10:30 tonight—text me at 10.”
5-Line Script
- “You want later. I get it—friends matter.”
- “Curfew tonight is 10:30. That’s our line.”
- “Plan: leave at 10:15, home by 10:30.”
- “Text me at 10 so I know you’re on time.”
- “If you’re late, tomorrow night ends earlier. Deal?”
ParentPal AI isn’t a substitute for medical care. If safety is a concern, contact a professional or emergency services.
How It Works
Step 1Ask Your Situation
We confirm your child’s exact age for a precise, age-fit answer.
Step 2Get Your Script
Five clear lines you can read aloud (gentle or firm options).
Step 3Use Tonight
Share or print so partners and carers are aligned.
The ParentPal Promise
🔒Private
🧠Evidence-Informed
🤝Judgment-Free
Age-fit, practical scripts you can use tonight.
Guidance only — not medical advice.
Parents Are Noticing
“Less chaos at bedtime.” — Sophia, Mum of 3
“Finally, words that land.” — Daniel, Dad of a 9-year-old
85%Report Calmer Evenings*
4.8/5Avg. Beta Rating
2k+Scripts Used
*Self-reported by beta users.
Our Approach
- Science, Simplified: Evidence-based child development and behavior—made practical.
- Age-First, Always: Guidance tailored to your child’s exact age.
- Clear Plans, Not Lectures: 5-step, do-tonight plans with teachable choices.
- Trusted Follow-Up: Links to respected sites and expert pages for deeper reading.
Is ParentPal really free?
Yes — chatting is free. The Free plan includes 3 full plans per conversation. Plus unlocks unlimited answers and clean printables.
Will you store my data?
ParentPal is private by default. We don’t sell personal data.
Do you replace a doctor or therapist?
No. ParentPal is guidance, not medical advice.
Can my partner use the same plan?
Yes — share or print clean PDFs for partners & caregivers.
What’s your refund policy?
30-day refund. Cancel anytime.
// Robust Chatbase opener (tries official API first, then clicks the bubble) function openParentPalChat(){ try{ if (window.chatbase && typeof window.chatbase === 'function') { window.chatbase('open'); return; } }catch(e){} const candidates = ['#chatbase-bubble','#cb-launcher','.cb-bubble','[class*="chatbase"] button']; for (const sel of candidates){ const el = document.querySelector(sel); if (el){ el.click(); return; } } window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); } document.getElementById('pp-open-chat')?.addEventListener('click', openParentPalChat); // Auto-hide CTA when footer anchors are on screen (so links are tappable) (function(){ const bar = document.querySelector('.pp-sticky-cta'); if (!bar) return; // Watch the footer anchors we added for the modals const targets = ['#open-privacy', '#open-terms', '#close'] .map(s => document.querySelector(s)) .filter(Boolean); if (!targets.length) return; const io = new IntersectionObserver((entries)=>{ // If any footer anchor is visible near the bottom, hide the bar const show = !entries.some(e => e.isIntersecting); bar.classList.toggle('is-hidden', !show); }, { root: null, threshold: 0.01, // start hiding when the element is within ~120px of viewport bottom rootMargin: '0px 0px -120px 0px' }); targets.forEach(t => io.observe(t)); })(); [email protected]
© 2025 ParentPal AI™. All rights reserved.
Privacy Policy | Terms
(function () { const VERIFY = 'https://api.parentpalway.com/api/verify'; const BADGE_ID = 'pp-plus-badge'; // -------- 0) Tiny helpers function applyPlan(isPlus) { const root = document.documentElement; if (isPlus) { root.classList.add('is-plus'); try { localStorage.setItem('pp_plan','plus'); } catch(e){} } else { root.classList.remove('is-plus'); try { localStorage.setItem('pp_plan','free'); } catch(e){} } } // Early cache to avoid flash try { if (localStorage.getItem('pp_plan') === 'plus') { document.documentElement.classList.add('is-plus'); } } catch(e){} // -------- 0.5) Chatbase refresh when Plus is detected function refreshChatbaseForPlus() { // Wipe obvious convo/session keys (best-effort) try { Object.keys(localStorage).forEach(function(k){ if (/chatbase|cb_|conversation|chatbot/i.test(k)) localStorage.removeItem(k); }); } catch(e){} // Reload the iframe now, or wait until it exists (consent-gated) function reloadFrameOnce(ifr) { try { const u = new URL(ifr.src, location.href); u.searchParams.set('pp_plus','1'); // harmless hint u.searchParams.set('ts', Date.now()); // bust cache ifr.src = u.toString(); } catch(e){ ifr.src = ifr.src; } } var ifr = document.querySelector('iframe[src*="chatbase"]'); if (ifr) { reloadFrameOnce(ifr); return; } // If not present yet, observe for it briefly let seen = false; const obs = new MutationObserver(() => { if (seen) return; const f = document.querySelector('iframe[src*="chatbase"]'); if (f) { seen = true; reloadFrameOnce(f); obs.disconnect(); } }); obs.observe(document.documentElement, { childList: true, subtree: true }); setTimeout(() => obs.disconnect(), 8000); } // -------- 1) Create badge function addBadge() { if (document.getElementById(BADGE_ID)) return; const b = document.createElement('div'); b.id = BADGE_ID; b.innerHTML = ` ★ParentPal Plus `; Object.assign(b.style, { position: 'fixed', right: '16px', bottom: '120px', zIndex: 2147483647, display: 'inline-flex', alignItems: 'center', gap: '6px', padding: '8px 12px', borderRadius: '999px', background: 'linear-gradient(135deg,#FFF6D7,#FFE39E)', color: '#0f172a', font: '600 12px/1 system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif', border: '1px solid rgba(0,0,0,.06)', boxShadow: '0 8px 22px rgba(0,0,0,.18), inset 0 1px 0 rgba(255,255,255,.6)', transition: 'left .2s ease, right .2s ease, bottom .2s ease' }); document.body.appendChild(b); } // -------- 2) Chat widget avoidance (unchanged) function $(sel){ return document.querySelector(sel); } function rect(el){ return el.getBoundingClientRect(); } function overlaps(a,b){ const pad=12; return !(a.right < b.left-pad || a.left > b.right+pad || a.bottom < b.top-pad || a.top > b.bottom+pad); } function getChatRect(){ const chatbase = document.querySelector('iframe[src*="chatbase.co/chatbot-iframe"]') || document.querySelector('iframe[src*="chatbase"]'); if (chatbase) return rect(chatbase); const ALL = document.querySelectorAll('body *'); let best = null, bestScore = -Infinity; for (const el of ALL){ if (el.id === BADGE_ID) continue; const cs = getComputedStyle(el); if (cs.position !== 'fixed') continue; const r = rect(el); const nearRight = (window.innerWidth - r.right) <= 220; const nearBottom = (window.innerHeight - r.bottom) <= 220; const bigEnough = r.width > 40 && r.height > 40; if (nearRight && nearBottom && bigEnough){ const score = r.right + r.bottom; if (score > bestScore){ bestScore = score; best = r; } } } return best; } function placeBadge(){ const b = document.getElementById(BADGE_ID); if (!b) return; const isMobile = window.matchMedia('(max-width: 767px)').matches; b.style.bottom = isMobile ? '100px' : '120px'; b.style.right = '16px'; const cr = getChatRect(); if (!cr) return; const br = rect(b); const tooClose = (window.innerWidth - cr.left) < 140; if (overlaps(br, cr) || tooClose){ const desiredRight = Math.max(16, Math.round(window.innerWidth - cr.left + 16)); b.style.right = desiredRight + 'px'; } } function startRepositioning(){ placeBadge(); let n = 0; const iv = setInterval(() => { placeBadge(); if (++n > 40) clearInterval(iv); }, 250); window.addEventListener('resize', placeBadge, { passive: true }); new MutationObserver(placeBadge).observe(document.documentElement, { childList: true, subtree: true }); window.addEventListener('load', placeBadge); } // -------- 3) Verify -> toggle class + badge (+ refresh chat if Plus) function init(){ fetch(VERIFY, { credentials: 'include' }) .then(r => r.json()) .then(d => { const isPlus = !!(d && d.plus); applyPlan(isPlus); if (isPlus){ addBadge(); startRepositioning(); refreshChatbaseForPlus(); // <— force fresh chat session after upgrade } else { const b = document.getElementById(BADGE_ID); if (b) b.remove(); } }) .catch(() => { applyPlan(false); }); } // If consent UI applies later and user is already Plus, refresh Chatbase then window.addEventListener('pp-consent-applied', function(e){ if (!document.documentElement.classList.contains('is-plus')) return; var s = e && e.detail ? e.detail : null; if (!s || s.marketing) { // marketing allowed or unknown → safe to refresh refreshChatbaseForPlus(); } }); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => setTimeout(init, 0), { once: true }); } else { setTimeout(init, 0); } })();
(function () { const BADGE_ID = 'pp-plus-badge'; const getBadge = () => document.getElementById(BADGE_ID); const rect = (el) => el.getBoundingClientRect(); const overlaps = (a, b) => !(a.right < b.left || a.left > b.right || a.bottom < b.top || a.top > b.bottom); // Prefer Chatbase iframe; if not found, fall back to "big fixed thing bottom-right" function getChatRect() { const chat = document.querySelector('iframe[src^="https://www.chatbase.co/chatbot-iframe/"]') || document.querySelector('iframe[src*="chatbase.co/chatbot-iframe"]') || document.querySelector('iframe[src*="chatbase"]'); if (chat) return rect(chat); // Fallback: biggest fixed element near bottom-right let bestRect = null, bestScore = -1; document.querySelectorAll('body *').forEach(el => { if (el.id === BADGE_ID) return; const cs = getComputedStyle(el); if (cs.position !== 'fixed') return; const r = rect(el); const nearRight = (innerWidth - r.right) <= 240; const nearBottom = (innerHeight - r.bottom) <= 240; const big = r.width > 40 && r.height > 40; if (nearRight && nearBottom && big) { const score = r.right + r.bottom; // closest to corner wins if (score > bestScore) { bestScore = score; bestRect = r; } } }); return bestRect; } function moveBadge() { const b = getBadge(); if (!b) return; // nothing to do if badge isn't on this session // default spot const mobile = matchMedia('(max-width: 767px)').matches; b.style.bottom = mobile ? '100px' : '120px'; b.style.right = '16px'; const cr = getChatRect(); if (!cr) return; // Detect “open” chat by size, or if we overlap → push left const looksOpen = cr.width >= 200 || cr.height >= 200; const br = rect(b); if (looksOpen || overlaps(br, cr)) { b.style.right = Math.max(16, Math.round(innerWidth - cr.left + 16)) + 'px'; } } // Nudge while things animate in let n = 0; const iv = setInterval(() => { moveBadge(); if (++n > 60) clearInterval(iv); }, 250); // Also react to resizes, DOM mutations, and page load addEventListener('resize', moveBadge, { passive: true }); new MutationObserver(moveBadge).observe(document.documentElement, { childList: true, subtree: true }); addEventListener('load', moveBadge); })();
/* Tiny forcer: keeps #pp-plus-badge out of the Chatbase panel */ (function () { const ID = 'pp-plus-badge'; // Find your Chatbase iframe (the big panel & the bubble are the same iframe) function chatRect() { const f = document.querySelector('iframe[src^="https://www.chatbase.co/chatbot-iframe/"]') || document.querySelector('iframe[src*="chatbase.co/chatbot-iframe"]') || document.querySelector('iframe[src*="chatbase"]'); return f ? f.getBoundingClientRect() : null; } function tick() { const b = document.getElementById(ID); if (!b) return; // badge not present (user not Plus yet) // add smooth movement once if (!b.dataset.hasTransition) { b.style.transition = 'right .2s ease, bottom .2s ease'; b.dataset.hasTransition = '1'; } // default spot const isMobile = matchMedia('(max-width: 767px)').matches; b.style.bottom = isMobile ? '100px' : '120px'; const cr = chatRect(); if (!cr) { b.style.right = '16px'; return; } // If panel looks open (wide/tall) push badge left to clear it (16px gap). const openish = cr.width >= 180 || cr.height >= 180; const desiredRight = openish ? Math.max(16, Math.round(innerWidth - cr.left + 16)) : 16; // Always enforce right so we "win" even if another script sets it back. b.style.right = desiredRight + 'px'; } // Run continuously so it also works during panel animations & iframes mounting let started = false; function start() { if (started) return; started = true; tick(); // immediate setInterval(tick, 200); // keep enforcing every 200ms addEventListener('resize', tick, { passive: true }); addEventListener('load', tick); new MutationObserver(tick).observe(document.documentElement, { childList: true, subtree: true }); } // Start when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', start, { once: true }); } else { start(); } })();