ProPeler
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
var
/
www
/
html
/
wp-content
/
themes
/
bayisihat-jurnal
/
inc
/
Filename :
features.php
back
Copy
<?php if (!defined('ABSPATH')) exit; /* ============ Bayi Sihat โ Features: newsletter, auto internal links, GA4, WhatsApp ============ */ /* ---------- 1. Newsletter (subscriber storage, no third-party needed) ---------- */ add_action('init', function(){ register_post_type('bs_subscriber', array( 'labels' => array('name'=>'Pelanggan Surat Berita','singular_name'=>'Pelanggan','menu_name'=>'Pelanggan Surat Berita'), 'public' => false, 'show_ui' => true, 'show_in_menu' => true, 'menu_icon' => 'dashicons-email-alt', 'supports' => array('title'), 'capability_type' => 'post', 'map_meta_cap' => true, )); }); function bs_subscribe_handler(){ if (!check_ajax_referer('bs_sub', 'nonce', false)) { wp_send_json_error(array('msg' => 'Sesi tamat โ sila muat semula halaman.')); } // honeypot: bots fill "website" โ pretend success silently if (!empty($_POST['website'])) { wp_send_json_success(array('msg' => 'Terima kasih! Anda telah dilanggan.', 'unlock' => false)); } $email = sanitize_email(wp_unslash($_POST['email'] ?? '')); if (!is_email($email)) { wp_send_json_error(array('msg' => 'Sila masukkan alamat e-mel yang sah.')); } $ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field($_SERVER['REMOTE_ADDR']) : ''; $tkey = 'bs_sub_' . md5($ip); if (get_transient($tkey)) { wp_send_json_error(array('msg' => 'Terlalu pantas โ sila cuba sebentar lagi.')); } set_transient($tkey, 1, 20); $src = sanitize_text_field(wp_unslash($_POST['src'] ?? 'newsletter')); $ebook = function_exists('bs_sub_ebook_url'); $existing = get_posts(array('post_type'=>'bs_subscriber','title'=>$email,'post_status'=>'any','numberposts'=>1,'fields'=>'ids')); if (!empty($existing)) { $sid = $existing[0]; update_post_meta($sid, 'bs_ebook_lead', current_time('mysql')); bs_mailerlite_sync($email, $src); wp_send_json_success(array( 'msg' => 'E-mel anda memang dalam senarai kami ๐ฑ Ebook & bonus anda di bawah.', 'unlock' => true, 'ebook' => $ebook ? bs_sub_ebook_url($sid) : '', )); } $id = wp_insert_post(array( 'post_type' => 'bs_subscriber', 'post_title' => $email, 'post_status' => 'publish', ), true); if (is_wp_error($id)) { wp_send_json_error(array('msg' => 'Maaf, ada masalah teknikal. Cuba lagi sebentar.')); } update_post_meta($id, 'bs_sub_ip', $ip); update_post_meta($id, 'bs_sub_date', current_time('mysql')); update_post_meta($id, 'bs_sub_src', $src); update_post_meta($id, 'bs_sub_source', esc_url_raw(wp_get_referer() ?: '')); update_post_meta($id, 'bs_ebook_lead', current_time('mysql')); bs_mailerlite_sync($email, $src); wp_send_json_success(array( 'msg' => 'Terima kasih! Anda kini pelanggan Bayi Sihat ๐ฑ Ebook anda sedia di bawah.', 'unlock' => true, 'ebook' => $ebook ? bs_sub_ebook_url($id) : '', )); } add_action('wp_ajax_nopriv_bs_subscribe', 'bs_subscribe_handler'); add_action('wp_ajax_bs_subscribe', 'bs_subscribe_handler'); /* Push subscriber to MailerLite (best-effort; local storage stays source of truth). Two steps: upsert subscriber, then assign to group (the create-call `groups` field is unreliable, so we use the dedicated assign endpoint). */ function bs_mailerlite_sync($email, $src = ''){ $token = trim(get_option('bs_mailerlite_token', '')); if (!$token || !is_email($email)) return false; $headers = array( 'Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/json', 'Accept' => 'application/json', ); $res = wp_remote_post('https://connect.mailerlite.com/api/subscribers', array( 'timeout' => 8, 'headers' => $headers, 'body' => wp_json_encode(array('email' => $email)), )); if (is_wp_error($res)) return false; $code = wp_remote_retrieve_response_code($res); if ($code < 200 || $code >= 300) return false; $data = json_decode(wp_remote_retrieve_body($res), true); $sid = isset($data['data']['id']) ? $data['data']['id'] : ''; $group = trim(get_option('bs_mailerlite_group', '')); if ($sid && $group) { wp_remote_post('https://connect.mailerlite.com/api/subscribers/' . rawurlencode($sid) . '/groups/' . rawurlencode($group), array( 'timeout' => 8, 'headers' => $headers, )); } return true; } // CSV export (admin) add_action('admin_post_bs_export_subs', function(){ if (!current_user_can('manage_options') || !wp_verify_nonce($_GET['_wpnonce'] ?? '', 'bs_export')) wp_die('Tidak dibenarkan'); $subs = get_posts(array('post_type'=>'bs_subscriber','numberposts'=>-1,'post_status'=>'publish')); header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename=bayisihat-subscribers-' . wp_date('Ymd') . '.csv'); $out = fopen('php://output', 'w'); fputcsv($out, array('email','tarikh','sumber')); foreach ($subs as $s) { fputcsv($out, array($s->post_title, get_post_meta($s->ID,'bs_sub_date',true), get_post_meta($s->ID,'bs_sub_source',true))); } fclose($out); exit; }); add_action('admin_notices', function(){ $screen = function_exists('get_current_screen') ? get_current_screen() : null; if (!$screen || $screen->post_type !== 'bs_subscriber') return; $count = wp_count_posts('bs_subscriber')->publish; $url = wp_nonce_url(admin_url('admin-post.php?action=bs_export_subs'), 'bs_export'); echo '<div class="notice notice-info"><p><strong>' . intval($count) . ' pelanggan.</strong> <a href="' . esc_url($url) . '" class="button">Muat turun CSV</a> โ boleh diimport ke MailerLite/Mailchimp bila-bila.</p></div>'; }); // Reusable newsletter form component (with lead magnet reveal) function bs_newsletter_form($title = '', $desc = ''){ $title = $title ?: 'Panduan mingguan, terus ke e-mel anda'; $desc = $desc ?: 'Langgan percuma & dapatkan 2 PDF bonus: Checklist Hospital Bag + Jadual Imunisasi (printable).'; $nonce = wp_create_nonce('bs_sub'); $ajax = admin_url('admin-ajax.php'); $up = wp_upload_dir(); $pdf1 = $up['baseurl'] . '/lead/checklist-hospital-bag-bayisihat.pdf'; $pdf2 = $up['baseurl'] . '/lead/jadual-imunisasi-bayisihat.pdf'; $wa = trim(get_option('bs_whatsapp_url', '')); ob_start(); ?> <div class="newsletter"> <div class="newsletter__text"> <h2><?php echo esc_html($title); ?></h2> <p><?php echo esc_html($desc); ?></p> <?php if ($wa): ?><p style="margin-top:.7rem"><a class="wa-channel" href="<?php echo esc_url($wa); ?>" target="_blank" rel="noopener">๐ฌ Sertai Komuniti WhatsApp Bayi Sihat</a></p><?php endif; ?> </div> <div class="newsletter__action"> <form class="newsletter__form bs-sub-form" data-nonce="<?php echo esc_attr($nonce); ?>" data-ajax="<?php echo esc_url($ajax); ?>"> <input type="email" name="email" required placeholder="Alamat e-mel anda" aria-label="Alamat e-mel"> <input type="text" name="website" class="bs-hp" tabindex="-1" autocomplete="off" aria-hidden="true"> <button class="btn btn--primary" type="submit">Langgan</button> </form> <div class="bs-sub-msg" role="status" aria-live="polite"></div> <div class="bs-sub-gift" hidden> <a class="bs-gift-link bs-ebook-dl" href="#" target="_blank" rel="noopener">๐ Ebook: Panduan Kehamilan Lengkap (73 m/s, PDF)</a> <a class="bs-gift-link" href="<?php echo esc_url($pdf1); ?>" target="_blank" rel="noopener">๐ Checklist Hospital Bag (PDF)</a> <a class="bs-gift-link" href="<?php echo esc_url($pdf2); ?>" target="_blank" rel="noopener">๐ Jadual Imunisasi Printable (PDF)</a> </div> </div> </div> <?php return ob_get_clean(); } /* ---------- 1b. Ebook lead-magnet hook (pancing dalam setiap artikel) ---------- */ function bs_ebook_hook(){ $nonce = wp_create_nonce('bs_sub'); $ajax = admin_url('admin-ajax.php'); ob_start(); ?> <aside class="bs-ebook-hook" aria-label="Ebook percuma"> <div class="bs-ebook-hook__cover" aria-hidden="true"> <span class="bs-ebook-hook__brand">BAYI SIHAT</span> <span class="bs-ebook-hook__ct">Panduan<br>Kehamilan<br>Lengkap</span> <span class="bs-ebook-hook__ed">73 m/s ยท PDF</span> </div> <div class="bs-ebook-hook__body"> <p class="bs-ebook-hook__tag">Ebook Percuma <s>RM19</s> <b>PERCUMA</b></p> <h3 class="bs-ebook-hook__title">Dapatkan Panduan Kehamilan Lengkap โ 73 muka surat</h3> <p class="bs-ebook-hook__desc">Semua panduan dari tanda awal hamil hingga hari bersalin, dalam satu PDF kemas untuk dibaca offline & dicetak. Masukkan e-mel โ terus dapat, tiada bayaran.</p> <form class="newsletter__form bs-sub-form" data-nonce="<?php echo esc_attr($nonce); ?>" data-ajax="<?php echo esc_url($ajax); ?>"> <input type="email" name="email" required placeholder="Alamat e-mel anda" aria-label="E-mel"> <input type="text" name="website" class="bs-hp" tabindex="-1" autocomplete="off" aria-hidden="true"> <input type="hidden" name="src" value="ebook-artikel"> <button class="btn btn--primary" type="submit">Dapatkan Ebook Percuma</button> </form> <div class="bs-sub-msg" role="status" aria-live="polite"></div> <div class="bs-sub-gift" hidden> <a class="bs-gift-link bs-ebook-dl" href="#" target="_blank" rel="noopener">๐ Muat Turun Ebook (PDF) โ</a> </div> <p class="bs-ebook-hook__trust">๐ Percuma ยท Tiada spam ยท Berhenti langgan bila-bila</p> </div> </aside> <?php return ob_get_clean(); } // Inject the ebook hook into the middle of every article (after the 4th paragraph). add_filter('the_content', 'bs_inject_ebook_hook', 25); function bs_inject_ebook_hook($content){ if (!is_singular('post') || !in_the_loop() || !is_main_query()) return $content; if (strpos($content, 'bs-ebook-hook') !== false) return $content; $hook = bs_ebook_hook(); $parts = preg_split('/(<\/p>)/i', $content, -1, PREG_SPLIT_DELIM_CAPTURE); $count = 0; $out = ''; $done = false; foreach ($parts as $p) { $out .= $p; if (strcasecmp($p, '</p>') === 0) { $count++; if ($count === 4 && !$done) { $out .= $hook; $done = true; } } } if (!$done) $out .= $hook; // fewer than 4 paragraphs โ append at end return $out; } /* ---------- 2. Auto internal linking (SEO) ---------- */ function bs_autolink_map(){ return array( 'jadual imunisasi bayi' => '/alat/jadual-imunisasi/', 'jadual imunisasi' => '/alat/jadual-imunisasi/', 'tarikh jangka bersalin' => '/alat/kalkulator-tarikh-bersalin/', 'kehamilan minggu demi minggu' => '/kehamilan-mingguan/', 'perkembangan bayi dalam kandungan' => '/kehamilan-mingguan/', 'nama bayi' => '/alat/nama-bayi/', 'berat badan bayi' => '/alat/berat-bayi/', 'kenaikan berat masa hamil' => '/alat/kalkulator-berat-kehamilan/', 'masa subur' => '/alat/kalkulator-ovulasi/', 'ovulasi' => '/alat/kalkulator-ovulasi/', 'milestone bayi' => '/alat/milestone-bayi/', 'perkembangan bayi ikut umur' => '/alat/milestone-bayi/', 'kuantiti susu bayi' => '/alat/kuantiti-susu-bayi/', 'kos bersalin' => '/alat/kos-bersalin/', 'hospital bag' => '/hospital-bag-bersalin-checklist/', 'berpantang' => '/panduan-berpantang-44-hari/', 'morning sickness' => '/morning-sickness-trimester-pertama/', 'kolik' => '/kolik-bayi-cara-tenangkan/', 'jaundis' => '/jaundis-kuning-bayi/', 'MPASI' => '/menu-mpasi-bayi-6-bulan/', 'susu formula' => '/cara-pilih-susu-formula-bayi/', ); } add_filter('the_content', 'bs_auto_link', 20); function bs_auto_link($content){ if (!is_singular('post') || !in_the_loop() || !is_main_query()) return $content; if (stripos($content, '<p') === false) return $content; $current = untrailingslashit((string) wp_parse_url(get_permalink(), PHP_URL_PATH)); $doc = new DOMDocument(); libxml_use_internal_errors(true); $ok = $doc->loadHTML('<?xml encoding="UTF-8"><div id="bsroot">' . $content . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); libxml_clear_errors(); if (!$ok) return $content; $xp = new DOMXPath($doc); $root = $xp->query('//div[@id="bsroot"]')->item(0); if (!$root) return $content; $made = 0; $used = array(); foreach (bs_autolink_map() as $kw => $path) { if ($made >= 4) break; if (isset($used[$path]) || untrailingslashit($path) === $current) continue; $nodes = $xp->query('.//p//text()[not(ancestor::a)] | .//li//text()[not(ancestor::a)]', $root); foreach ($nodes as $node) { $text = $node->nodeValue; $pos = mb_stripos($text, $kw); if ($pos === false) continue; $before = mb_substr($text, 0, $pos); $match = mb_substr($text, $pos, mb_strlen($kw)); $after = mb_substr($text, $pos + mb_strlen($kw)); $a = $doc->createElement('a'); $a->setAttribute('href', home_url($path)); $a->setAttribute('class', 'bs-auto-link'); $a->appendChild($doc->createTextNode($match)); $parent = $node->parentNode; if ($before !== '') $parent->insertBefore($doc->createTextNode($before), $node); $parent->insertBefore($a, $node); if ($after !== '') $parent->insertBefore($doc->createTextNode($after), $node); $parent->removeChild($node); $made++; $used[$path] = 1; break; } } if ($made === 0) return $content; $html = ''; foreach ($root->childNodes as $child) { $html .= $doc->saveHTML($child); } return $html; } /* ---------- 2b. Slide-in capture pada artikel ---------- */ add_action('wp_footer', function(){ if (!is_singular('post')) return; echo '<aside class="bs-slidein" id="bs-slidein" hidden aria-label="Langgan surat berita">' . '<button class="bs-slidein__close" type="button" aria-label="Tutup">ร</button>' . '<p class="bs-slidein__title">๐ Ebook Kehamilan PERCUMA</p>' . '<p class="bs-slidein__desc">73 muka surat โ tanda awal hamil hingga bersalin. Masukkan e-mel, terus dapat.</p>' . '<form class="newsletter__form bs-sub-form" data-nonce="' . esc_attr(wp_create_nonce('bs_sub')) . '" data-ajax="' . esc_url(admin_url('admin-ajax.php')) . '">' . '<input type="email" name="email" required placeholder="E-mel anda" aria-label="E-mel">' . '<input type="text" name="website" class="bs-hp" tabindex="-1" autocomplete="off" aria-hidden="true">' . '<input type="hidden" name="src" value="slidein-artikel">' . '<button class="btn btn--primary" type="submit">Dapatkan Percuma</button></form>' . '<div class="bs-sub-msg" role="status"></div>' . '<div class="bs-sub-gift" hidden><a class="bs-gift-link bs-ebook-dl" href="#" target="_blank" rel="noopener">๐ Muat Turun Ebook (PDF) โ</a></div>' . '</aside>'; }, 60); /* ---------- 3. Google Analytics 4 (set option bs_ga4_id, e.g. G-XXXXXXX) ---------- */ add_action('wp_head', function(){ $id = trim(get_option('bs_ga4_id', '')); if (!$id || is_user_logged_in()) return; echo "\n<script async src=\"https://www.googletagmanager.com/gtag/js?id=" . esc_attr($id) . "\"></script>\n"; echo "<script>window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','" . esc_js($id) . "');</script>\n"; }, 8);