{"id":240696,"date":"2025-07-17T16:18:35","date_gmt":"2025-07-17T16:18:35","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/init-user-engine\/"},"modified":"2026-09-04T13:49:09","modified_gmt":"2026-09-04T13:49:09","slug":"init-user-engine","status":"publish","type":"plugin","link":"https:\/\/oci.wordpress.org\/plugins\/init-user-engine\/","author":14479633,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.6.2","stable_tag":"1.6.2","tested":"7.1","requires":"5.5","requires_php":"7.4","requires_plugins":null,"header_name":"Init User Engine","header_author":"Init HTML","header_description":"Lightweight, gamified user engine with EXP, wallet, check-in, VIP, inbox, and referral \u2013 powered by REST API and Vanilla JS.","assets_banners_color":"535076","last_updated":"2026-09-04 13:49:09","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/inithtml.com\/plugin\/init-user-engine\/","header_author_uri":"https:\/\/inithtml.com\/","rating":5,"author_block_rating":0,"active_installs":40,"downloads":4342,"num_ratings":1,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.1":{"tag":"1.0.1","author":"brokensmile.2103","date":"2025-07-17 16:17:59","revision":3329854},"1.0.2":{"tag":"1.0.2","author":"brokensmile.2103","date":"2025-07-21 15:31:44","revision":3331601},"1.0.3":{"tag":"1.0.3","author":"brokensmile.2103","date":"2025-07-22 19:28:16","revision":3332488},"1.0.4":{"tag":"1.0.4","author":"brokensmile.2103","date":"2025-07-23 00:44:36","revision":3332556},"1.0.5":{"tag":"1.0.5","author":"brokensmile.2103","date":"2025-07-23 03:03:08","revision":3332573},"1.0.6":{"tag":"1.0.6","author":"brokensmile.2103","date":"2025-07-28 16:02:02","revision":3335470},"1.0.7":{"tag":"1.0.7","author":"brokensmile.2103","date":"2025-07-30 19:19:05","revision":3336829},"1.0.8":{"tag":"1.0.8","author":"brokensmile.2103","date":"2025-07-31 05:24:23","revision":3336967},"1.0.9":{"tag":"1.0.9","author":"brokensmile.2103","date":"2025-08-03 11:59:40","revision":3338441},"1.1.0":{"tag":"1.1.0","author":"brokensmile.2103","date":"2025-08-14 16:19:16","revision":3344780},"1.1.1":{"tag":"1.1.1","author":"brokensmile.2103","date":"2025-08-18 05:58:01","revision":3346131},"1.1.2":{"tag":"1.1.2","author":"brokensmile.2103","date":"2025-08-19 14:56:12","revision":3347099},"1.1.3":{"tag":"1.1.3","author":"brokensmile.2103","date":"2025-08-21 18:31:46","revision":3348316},"1.1.4":{"tag":"1.1.4","author":"brokensmile.2103","date":"2025-08-21 18:46:16","revision":3348322},"1.1.5":{"tag":"1.1.5","author":"brokensmile.2103","date":"2025-08-22 06:32:12","revision":3348462},"1.1.6":{"tag":"1.1.6","author":"brokensmile.2103","date":"2025-08-23 13:26:10","revision":3348985},"1.1.7":{"tag":"1.1.7","author":"brokensmile.2103","date":"2025-08-30 05:17:46","revision":3352973},"1.1.8":{"tag":"1.1.8","author":"brokensmile.2103","date":"2025-09-17 13:23:06","revision":3363239},"1.1.9":{"tag":"1.1.9","author":"brokensmile.2103","date":"2025-09-17 14:02:49","revision":3363269},"1.2.0":{"tag":"1.2.0","author":"brokensmile.2103","date":"2025-09-28 03:46:42","revision":3369073},"1.2.1":{"tag":"1.2.1","author":"brokensmile.2103","date":"2025-09-28 15:13:53","revision":3369239},"1.2.2":{"tag":"1.2.2","author":"brokensmile.2103","date":"2025-10-03 05:13:37","revision":3372128},"1.2.3":{"tag":"1.2.3","author":"brokensmile.2103","date":"2025-10-03 13:50:37","revision":3372398},"1.2.4":{"tag":"1.2.4","author":"brokensmile.2103","date":"2025-10-04 07:25:54","revision":3372735},"1.2.5":{"tag":"1.2.5","author":"brokensmile.2103","date":"2025-10-04 15:11:21","revision":3372880},"1.2.6":{"tag":"1.2.6","author":"brokensmile.2103","date":"2025-10-05 05:30:38","revision":3373020},"1.2.7":{"tag":"1.2.7","author":"brokensmile.2103","date":"2025-10-08 02:35:11","revision":3374753},"1.2.8":{"tag":"1.2.8","author":"brokensmile.2103","date":"2025-10-10 09:50:14","revision":3376152},"1.2.9":{"tag":"1.2.9","author":"brokensmile.2103","date":"2025-10-10 12:16:12","revision":3376221},"1.3.0":{"tag":"1.3.0","author":"brokensmile.2103","date":"2025-10-12 05:29:40","revision":3376832},"1.3.1":{"tag":"1.3.1","author":"brokensmile.2103","date":"2025-10-17 14:40:36","revision":3380195},"1.3.2":{"tag":"1.3.2","author":"brokensmile.2103","date":"2025-10-18 13:31:39","revision":3380537},"1.3.3":{"tag":"1.3.3","author":"brokensmile.2103","date":"2025-10-23 05:20:00","revision":3383060},"1.3.4":{"tag":"1.3.4","author":"brokensmile.2103","date":"2025-10-23 08:09:21","revision":3383150},"1.3.5":{"tag":"1.3.5","author":"brokensmile.2103","date":"2025-10-27 05:08:34","revision":3384944},"1.3.6":{"tag":"1.3.6","author":"brokensmile.2103","date":"2025-10-27 06:18:59","revision":3384975},"1.3.7":{"tag":"1.3.7","author":"brokensmile.2103","date":"2025-10-29 06:36:32","revision":3386208},"1.3.7.1":{"tag":"1.3.7.1","author":"brokensmile.2103","date":"2025-10-29 06:36:32","revision":3386208},"1.3.8":{"tag":"1.3.8","author":"brokensmile.2103","date":"2025-10-30 08:55:03","revision":3386913},"1.3.8.1":{"tag":"1.3.8.1","author":"brokensmile.2103","date":"2025-10-30 14:28:26","revision":3387141},"1.3.9":{"tag":"1.3.9","author":"brokensmile.2103","date":"2025-11-03 07:09:53","revision":3388640},"1.4.0":{"tag":"1.4.0","author":"brokensmile.2103","date":"2025-11-04 16:44:31","revision":3389813},"1.4.1":{"tag":"1.4.1","author":"brokensmile.2103","date":"2025-11-17 04:25:44","revision":3396870},"1.4.2":{"tag":"1.4.2","author":"brokensmile.2103","date":"2025-11-19 05:43:40","revision":3398509},"1.4.3":{"tag":"1.4.3","author":"brokensmile.2103","date":"2026-01-28 06:38:32","revision":3448397},"1.4.4":{"tag":"1.4.4","author":"brokensmile.2103","date":"2026-02-04 06:27:58","revision":3453513},"1.4.5":{"tag":"1.4.5","author":"brokensmile.2103","date":"2026-02-04 07:11:09","revision":3453557},"1.4.6":{"tag":"1.4.6","author":"brokensmile.2103","date":"2026-02-07 02:15:20","revision":3455726},"1.4.7":{"tag":"1.4.7","author":"brokensmile.2103","date":"2026-03-24 14:52:29","revision":3490129},"1.4.8":{"tag":"1.4.8","author":"brokensmile.2103","date":"2026-03-25 04:26:50","revision":3490489},"1.4.9":{"tag":"1.4.9","author":"brokensmile.2103","date":"2026-04-15 15:58:00","revision":3507249},"1.5.0":{"tag":"1.5.0","author":"brokensmile.2103","date":"2026-04-21 08:21:47","revision":3511523},"1.5.0.1":{"tag":"1.5.0.1","author":"brokensmile.2103","date":"2026-04-21 09:27:14","revision":3511585},"1.5.0.2":{"tag":"1.5.0.2","author":"brokensmile.2103","date":"2026-04-21 12:37:20","revision":3511809},"1.5.0.3":{"tag":"1.5.0.3","author":"brokensmile.2103","date":"2026-04-21 13:41:10","revision":3511884},"1.5.1":{"tag":"1.5.1","author":"brokensmile.2103","date":"2026-05-17 14:13:26","revision":3534601},"1.5.2":{"tag":"1.5.2","author":"brokensmile.2103","date":"2026-05-17 15:19:26","revision":3534639},"1.5.3":{"tag":"1.5.3","author":"brokensmile.2103","date":"2026-07-29 06:30:59","revision":3626741},"1.5.4":{"tag":"1.5.4","author":"brokensmile.2103","date":"2026-08-11 08:06:58","revision":3641511},"1.5.5":{"tag":"1.5.5","author":"brokensmile.2103","date":"2026-08-11 18:18:23","revision":3642371},"1.5.6":{"tag":"1.5.6","author":"brokensmile.2103","date":"2026-08-16 03:39:55","revision":3649241},"1.5.7":{"tag":"1.5.7","author":"brokensmile.2103","date":"2026-08-16 10:42:56","revision":3649617},"1.5.8":{"tag":"1.5.8","author":"brokensmile.2103","date":"2026-08-22 15:05:28","revision":3660771},"1.5.9":{"tag":"1.5.9","author":"brokensmile.2103","date":"2026-08-29 08:03:26","revision":3671242},"1.6.0":{"tag":"1.6.0","author":"brokensmile.2103","date":"2026-09-03 05:53:32","revision":3679046},"1.6.1":{"tag":"1.6.1","author":"brokensmile.2103","date":"2026-09-04 05:46:39","revision":3680680},"1.6.2":{"tag":"1.6.2","author":"brokensmile.2103","date":"2026-09-04 13:49:09","revision":3681309}},"upgrade_notice":[],"ratings":{"1":0,"2":0,"3":0,"4":0,"5":1},"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3329854,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3329854,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3329854,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3329854,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.1","1.0.2","1.0.3","1.0.4","1.0.5","1.0.6","1.0.7","1.0.8","1.0.9","1.1.0","1.1.1","1.1.2","1.1.3","1.1.4","1.1.5","1.1.6","1.1.7","1.1.8","1.1.9","1.2.0","1.2.1","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.2.7","1.2.8","1.2.9","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.3.6","1.3.7","1.3.7.1","1.3.8","1.3.8.1","1.3.9","1.4.0","1.4.1","1.4.2","1.4.3","1.4.4","1.4.5","1.4.6","1.4.7","1.4.8","1.4.9","1.5.0","1.5.0.1","1.5.0.2","1.5.0.3","1.5.1","1.5.2","1.5.3","1.5.4","1.5.5","1.5.6","1.5.7","1.5.8","1.5.9","1.6.0","1.6.1","1.6.2"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3678614,"resolution":"1","location":"assets","locale":"","width":1298,"height":2460},"screenshot-10.png":{"filename":"screenshot-10.png","revision":3329854,"resolution":"10","location":"assets","locale":"","width":650,"height":700},"screenshot-11.png":{"filename":"screenshot-11.png","revision":3329854,"resolution":"11","location":"assets","locale":"","width":403,"height":592},"screenshot-12.png":{"filename":"screenshot-12.png","revision":3329854,"resolution":"12","location":"assets","locale":"","width":664,"height":814},"screenshot-13.png":{"filename":"screenshot-13.png","revision":3329854,"resolution":"13","location":"assets","locale":"","width":664,"height":905},"screenshot-14.png":{"filename":"screenshot-14.png","revision":3329854,"resolution":"14","location":"assets","locale":"","width":664,"height":905},"screenshot-15.png":{"filename":"screenshot-15.png","revision":3329854,"resolution":"15","location":"assets","locale":"","width":664,"height":905},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3626741,"resolution":"2","location":"assets","locale":"","width":967,"height":298},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3626741,"resolution":"3","location":"assets","locale":"","width":633,"height":393},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3626741,"resolution":"4","location":"assets","locale":"","width":646,"height":485},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3626741,"resolution":"5","location":"assets","locale":"","width":719,"height":1581},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3626741,"resolution":"6","location":"assets","locale":"","width":632,"height":448},"screenshot-7.png":{"filename":"screenshot-7.png","revision":3626741,"resolution":"7","location":"assets","locale":"","width":691,"height":670},"screenshot-8.png":{"filename":"screenshot-8.png","revision":3626741,"resolution":"8","location":"assets","locale":"","width":846,"height":1098},"screenshot-9.png":{"filename":"screenshot-9.png","revision":3329854,"resolution":"9","location":"assets","locale":"","width":650,"height":650}},"screenshots":{"1":"Settings with options for theme color, currency labels, and admin bar\/Gravatar control.","2":"Custom Links section for setting Register and Lost Password URLs.","3":"Check-in Reward configuration, including Coin, EXP, and Cash per check-in.","4":"Online Reward configuration based on active time with reward values.","5":"VIP Pricing options for various durations, including lifetime.","6":"VIP Bonus settings to configure extra Coin\/EXP for VIP users.","7":"Referral Reward settings for both referrer and new user.","8":"Admin panel to send notifications with content, targeting, priority, and expiration.","9":"Login modal interface for non-logged-in users.","10":"Registration modal with username, email, and password fields.","11":"Avatar button with dropdown panel showing user info, level, stats, and quick links.","12":"VIP Membership modal with Coin-based purchase options and expiration note.","13":"Inbox modal showing system messages, rewards, and user notifications.","14":"Transaction history modal showing all reward activities (check-in, referral, online time...).","15":"Referral modal with shareable code\/link, social sharing buttons, and referral history."}},"plugin_section":[262246],"plugin_tags":[27702,2108,387,2153,51149],"plugin_category":[],"plugin_contributors":[242666],"plugin_business_model":[],"class_list":["post-240696","plugin","type-plugin","status-publish","hentry","plugin_section-dashboard-widgets","plugin_tags-check-in","plugin_tags-level","plugin_tags-referral","plugin_tags-user","plugin_tags-vip","plugin_contributors-brokensmile2103-1","plugin_committers-brokensmile2103-1"],"banners":{"banner":"https:\/\/ps.w.org\/init-user-engine\/assets\/banner-772x250.png?rev=3329854","banner_2x":"https:\/\/ps.w.org\/init-user-engine\/assets\/banner-1544x500.png?rev=3329854","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/init-user-engine\/assets\/icon-128x128.png?rev=3329854","icon_2x":"https:\/\/ps.w.org\/init-user-engine\/assets\/icon-256x256.png?rev=3329854","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-1.png?rev=3678614","caption":"Settings with options for theme color, currency labels, and admin bar\/Gravatar control."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-2.png?rev=3626741","caption":"Custom Links section for setting Register and Lost Password URLs."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-3.png?rev=3626741","caption":"Check-in Reward configuration, including Coin, EXP, and Cash per check-in."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-4.png?rev=3626741","caption":"Online Reward configuration based on active time with reward values."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-5.png?rev=3626741","caption":"VIP Pricing options for various durations, including lifetime."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-6.png?rev=3626741","caption":"VIP Bonus settings to configure extra Coin\/EXP for VIP users."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-7.png?rev=3626741","caption":"Referral Reward settings for both referrer and new user."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-8.png?rev=3626741","caption":"Admin panel to send notifications with content, targeting, priority, and expiration."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-9.png?rev=3329854","caption":"Login modal interface for non-logged-in users."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-10.png?rev=3329854","caption":"Registration modal with username, email, and password fields."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-11.png?rev=3329854","caption":"Avatar button with dropdown panel showing user info, level, stats, and quick links."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-12.png?rev=3329854","caption":"VIP Membership modal with Coin-based purchase options and expiration note."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-13.png?rev=3329854","caption":"Inbox modal showing system messages, rewards, and user notifications."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-14.png?rev=3329854","caption":"Transaction history modal showing all reward activities (check-in, referral, online time...)."},{"src":"https:\/\/ps.w.org\/init-user-engine\/assets\/screenshot-15.png?rev=3329854","caption":"Referral modal with shareable code\/link, social sharing buttons, and referral history."}],"raw_content":"<!--section=description-->\n<p><strong>Init User Engine<\/strong> is a lightweight, no-bloat user system for modern WordPress sites. It's designed for maximum frontend flexibility and gamified user engagement. All dynamic interfaces are rendered via JavaScript with real-time REST API interaction.<\/p>\n\n<p>No jQuery. Minimal settings. Smart by default.<\/p>\n\n<p>What you get:<\/p>\n\n<ul>\n<li>Display user avatar and dashboard via shortcode<\/li>\n<li>Show level, EXP, Coin\/Cash, and full user wallet<\/li>\n<li>Let users check-in daily and receive timed rewards<\/li>\n<li>Auto-track referral registrations with reward system<\/li>\n<li>Allow users to buy VIP status using in-site currency<\/li>\n<li>Built-in inbox for notifications (uses custom DB table)<\/li>\n<li>Custom avatar support with upload &amp; preview modal<\/li>\n<li>Send custom notifications to selected users or all members from wp-admin<\/li>\n<li>Optional \"Require Login to Access Site\" mode that gates the entire frontend behind the built-in login modal<\/li>\n<\/ul>\n\n<p>This plugin is the core user system behind the <a href=\"https:\/\/en.inithtml.com\/init-plugin-suite-minimalist-powerful-and-free-wordpress-plugins\/\">Init Plugin Suite<\/a> \u2013 optimized for frontend-first interaction, extensibility, and real-time gamification.<\/p>\n\n<p>GitHub repository: <a href=\"https:\/\/github.com\/brokensmile2103\/init-user-engine\">https:\/\/github.com\/brokensmile2103\/init-user-engine<\/a><\/p>\n\n<h3>Features<\/h3>\n\n<ul>\n<li>Avatar shortcode <code>[init_user_engine]<\/code> + modal dashboard  <\/li>\n<li>Avatar system with upload, preview, and revert support  <\/li>\n<li>EXP &amp; Level system with hookable progression logic  <\/li>\n<li>Coin &amp; Cash wallet system with transaction logs  <\/li>\n<li>Daily check-in with streak milestones &amp; online bonus timer  <\/li>\n<li>Inbox system with pagination, read\/claim\/delete  <\/li>\n<li>VIP membership system with Coin-based purchase &amp; expiry  <\/li>\n<li>Referral module with cookie-based signup tracking  <\/li>\n<li>Redeem Code \/ Gift Code module \u2013 code in, rewards out<\/li>\n<li>REST API for all features (read\/write\/modify)  <\/li>\n<li>Action\/filter hooks for full customization  <\/li>\n<li>Pure Vanilla JS frontend \u2013 no jQuery, no server bloat  <\/li>\n<li>Admin notification panel to send messages to selected users or all members<\/li>\n<\/ul>\n\n<h3>Developer Hooks<\/h3>\n\n<h3>Filters<\/h3>\n\n<ul>\n<li><code>init_plugin_suite_user_engine_online_minutes<\/code> \u2013 Modify required online minutes after check-in  <\/li>\n<li><code>init_plugin_suite_user_engine_vip_prices<\/code> \u2013 Modify VIP package prices  <\/li>\n<li><code>init_plugin_suite_user_engine_referral_rewards<\/code> \u2013 Modify referral rewards  <\/li>\n<li><code>init_plugin_suite_user_engine_localized_data<\/code> \u2013 Modify frontend JS data  <\/li>\n<li><code>init_plugin_suite_user_engine_calculated_coin_amount<\/code> \u2013 Modify Coin reward before apply  <\/li>\n<li><code>init_plugin_suite_user_engine_calculated_exp_amount<\/code> \u2013 Modify EXP reward before apply  <\/li>\n<li><code>init_plugin_suite_user_engine_exp_required<\/code> \u2013 Modify EXP required per level  <\/li>\n<li><code>init_plugin_suite_user_engine_checkin_milestones<\/code> \u2013 Set milestone streak days  <\/li>\n<li><code>init_plugin_suite_user_engine_format_inbox<\/code> \u2013 Modify formatted inbox data  <\/li>\n<li><code>init_plugin_suite_user_engine_render_level_badge<\/code> \u2013 Customize level badge HTML  <\/li>\n<li><code>init_plugin_suite_user_engine_inbox_insert_data<\/code> \u2013 Modify inbox data before inserting into database  <\/li>\n<li><code>init_plugin_suite_user_engine_validate_register_fields<\/code> \u2013 Validate or modify registration fields before account creation  <\/li>\n<li><code>init_plugin_suite_user_engine_after_register<\/code> \u2013 Hook after successful user registration (pass user ID and submitted data)  <\/li>\n<li><code>init_plugin_suite_user_engine_daily_tasks<\/code> \u2013 Add or modify daily task list and logic  <\/li>\n<li><code>init_plugin_suite_user_engine_captcha_bank<\/code> \u2013 Extend or modify the internal captcha question bank used for fallback validation  <\/li>\n<li><code>init_plugin_suite_user_engine_format_log_message<\/code> \u2013 Customize transaction log message display with access to entry data, source, type, and amount  <\/li>\n<li><code>init_plugin_suite_user_engine_should_keep_original<\/code> \u2013 Override decision to keep original uploaded avatar (GIF or other formats)  <\/li>\n<li><code>init_plugin_suite_user_engine_vip_expire_soon_threshold<\/code> \u2013 Modify the threshold (in seconds) used to determine when VIP is considered close to expiration  <\/li>\n<li><code>init_plugin_suite_user_engine_body_vip_classes<\/code> \u2013 Add, remove, or modify VIP-related CSS classes applied to the <code>&lt;body&gt;<\/code> element<\/li>\n<li><code>init_plugin_suite_user_engine_theme_colors<\/code> \u2013 Modify theme color system (primary and active colors)<\/li>\n<\/ul>\n\n<h3>Actions<\/h3>\n\n<ul>\n<li><code>init_plugin_suite_user_engine_level_up<\/code> \u2013 When user levels up  <\/li>\n<li><code>init_plugin_suite_user_engine_exp_added<\/code> \u2013 After EXP is added  <\/li>\n<li><code>init_plugin_suite_user_engine_transaction_logged<\/code> \u2013 After Coin\/Cash is logged  <\/li>\n<li><code>init_plugin_suite_user_engine_exp_logged<\/code> \u2013 After EXP log is recorded  <\/li>\n<li><code>init_plugin_suite_user_engine_inbox_inserted<\/code> \u2013 After new inbox message  <\/li>\n<li><code>init_plugin_suite_user_engine_referral_completed<\/code> \u2013 When referral is completed  <\/li>\n<li><code>init_plugin_suite_user_engine_after_checkin<\/code> \u2013 After user check-in  <\/li>\n<li><code>init_plugin_suite_user_engine_after_claim_reward<\/code> \u2013 After user claims reward  <\/li>\n<li><code>init_plugin_suite_user_engine_vip_purchased<\/code> \u2013 After VIP is purchased  <\/li>\n<li><code>init_plugin_suite_user_engine_add_exp<\/code> \u2013 Triggered when adding EXP via hook  <\/li>\n<li><code>init_plugin_suite_user_engine_add_coin<\/code> \u2013 Triggered when adding Coin via hook  <\/li>\n<li><code>init_plugin_suite_user_engine_coin_changed<\/code> \u2013 After user\u2019s Coin balance is updated  <\/li>\n<li><code>init_plugin_suite_user_engine_cash_changed<\/code> \u2013 After user\u2019s Cash balance is updated  <\/li>\n<li><code>init_plugin_suite_user_engine_admin_send_notice<\/code> \u2013 When admin sends notification via wp-admin.<\/li>\n<\/ul>\n\n<h3>REST API Endpoints<\/h3>\n\n<p><strong>Base:<\/strong> <code>\/wp-json\/inituser\/v1\/<\/code><\/p>\n\n<ul>\n<li><code>POST \/register<\/code> \u2013 Create a new user account  <\/li>\n<li><code>POST \/checkin<\/code> \u2013 Daily check-in  <\/li>\n<li><code>POST \/claim-reward<\/code> \u2013 Claim reward after online duration  <\/li>\n<li><code>GET  \/transactions<\/code> \u2013 Get Coin\/Cash transaction log  <\/li>\n<li><code>GET  \/exp-log<\/code> \u2013 Get EXP log  <\/li>\n<li><code>GET  \/inbox<\/code> \u2013 Get inbox messages  <\/li>\n<li><code>POST \/inbox\/mark-read<\/code> \u2013 Mark a message as read  <\/li>\n<li><code>POST \/inbox\/mark-all-read<\/code> \u2013 Mark all as read  <\/li>\n<li><code>POST \/inbox\/delete<\/code> \u2013 Delete a single message  <\/li>\n<li><code>POST \/inbox\/delete-all<\/code> \u2013 Delete all messages  <\/li>\n<li><code>POST \/vip\/purchase<\/code> \u2013 Purchase VIP package  <\/li>\n<li><code>GET  \/referral-log<\/code> \u2013 Get referral history  <\/li>\n<li><code>POST \/avatar<\/code> \u2013 Upload new avatar  <\/li>\n<li><code>POST \/avatar\/remove<\/code> \u2013 Remove custom avatar and revert to default  <\/li>\n<li><code>GET  \/profile\/me<\/code> \u2013 Get current user profile  <\/li>\n<li><code>POST \/profile\/update<\/code> \u2013 Update profile information<\/li>\n<li><code>GET  \/daily-tasks<\/code> \u2013 Get list of completed daily tasks and rewards<\/li>\n<li><code>POST \/exchange<\/code> \u2013 Convert Cash \u2192 Coin based on exchange rate<\/li>\n<li><code>POST \/redeem-code<\/code> \u2013 Redeem gift code (returns Coin\/Cash rewards)<\/li>\n<\/ul>\n\n<h3>License<\/h3>\n\n<p>This plugin is licensed under the GPLv2 or later.<br \/>\nYou are free to use, modify, and distribute it under the same license.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin to <code>\/wp-content\/plugins\/init-user-engine<\/code>  <\/li>\n<li>Activate it via the Plugins screen  <\/li>\n<li>Use <code>[init_user_engine]<\/code> in any page\/post\/template  <\/li>\n<li>You're done \u2013 modals and logic load automatically<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"how%20do%20i%20customize%20the%20ui%3F\"><h3>How do I customize the UI?<\/h3><\/dt>\n<dd><p>The frontend is written in modular Vanilla JS with minimal HTML structure.<br \/>\nOverride styles via your theme or inject custom JS as needed.<\/p><\/dd>\n<dt id=\"where%20is%20user%20data%20stored%3F\"><h3>Where is user data stored?<\/h3><\/dt>\n<dd><ul>\n<li><code>user_meta<\/code>: EXP, level, Coin, Cash, VIP, referral  <\/li>\n<li><code>wp_init_user_engine_inbox<\/code>: inbox messages (custom DB table)<\/li>\n<\/ul><\/dd>\n<dt id=\"can%20i%20extend%20or%20integrate%20it%3F\"><h3>Can I extend or integrate it?<\/h3><\/dt>\n<dd><p>Yes. The plugin is built around WordPress hooks and REST API. You can inject logic via <code>add_action<\/code>, <code>add_filter<\/code>, or build your own UI on top of the endpoints.<\/p><\/dd>\n<dt id=\"is%20it%20compatible%20with%20woocommerce%20or%20buddypress%3F\"><h3>Is it compatible with WooCommerce or BuddyPress?<\/h3><\/dt>\n<dd><p>Not officially, but it\u2019s modular and can be integrated via code or future addons.<\/p><\/dd>\n<dt id=\"how%20do%20i%20send%20messages%20to%20users%20manually%3F\"><h3>How do I send messages to users manually?<\/h3><\/dt>\n<dd><p>Go to <strong>Users \u2192 Init User Engine \u2192 Send Notification<\/strong> in wp-admin.<br \/>\nYou can search users, customize message type, link, priority, and even set expiration.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.6.2 \u2013 September 4, 2026<\/h4>\n\n<ul>\n<li>Changed: a pinned Inbox message now only stays pinned to the top while it is <strong>unread<\/strong>. As soon as it's marked as read (single message or \"mark all as read\"), it automatically unpins and behaves like any other message, so read messages no longer take up space at the top of the Inbox modal\n\n<ul>\n<li>Implemented by clearing <code>pinned<\/code> back to <code>0<\/code> in the exact same <code>UPDATE<\/code> query that already sets a message to <code>read<\/code> (<code>init_plugin_suite_user_engine_mark_inbox_read()<\/code> and the \"mark all as read\" REST endpoint) \u2014 no extra query, no change to the Inbox <code>SELECT<\/code>\/<code>ORDER BY<\/code>, and no new database index needed<\/li>\n<li>Added a one-time backfill (runs once on upgrade, same mechanism already used for schema updates) that clears <code>pinned<\/code> for any pre-existing message that was already pinned <strong>and<\/strong> read before this update<\/li>\n<li>Added a client-side safety net in the Inbox renderer so the pin icon never shows on a read message, even for the brief moment before the backfill above has run<\/li>\n<\/ul><\/li>\n<li>Updated <code>.pot<\/code>\/<code>.po<\/code> translation files (no new strings were needed for this change; existing ones were already sufficient)<\/li>\n<\/ul>\n\n<h4>1.6.1 \u2013 September 4, 2026<\/h4>\n\n<ul>\n<li>Added <strong>Export CSV<\/strong> for both code list screens (User Engine \u2192 Redeem Codes \/ VIP Codes)\n\n<ul>\n<li>New \"Export CSV\" button next to the \"Existing Redeem Codes\" \/ \"Existing VIP Codes\" heading, exporting the <strong>entire list<\/strong> (every page, not just the current one) as a downloadable <code>.csv<\/code> file<\/li>\n<li>Redeem Codes CSV columns: ID, Code, Type, Locked User ID, Locked Username, Coin Amount, Cash Amount, Max Uses, Used Count, Status, Valid From, Valid To, Created By, Created At, Updated At<\/li>\n<li>VIP Codes CSV columns: same as above, with VIP Days in place of Coin\/Cash Amount<\/li>\n<li>Data is streamed straight to the browser in batches of 500 rows so memory usage stays low even on sites with a large number of codes<\/li>\n<li>File is written with a UTF-8 BOM so it opens correctly in Excel, and every cell is sanitized against CSV\/formula injection (values starting with <code>=<\/code>, <code>+<\/code>, <code>-<\/code>, <code>@<\/code>, or a tab are safely prefixed)<\/li>\n<li>Gated behind the <code>manage_options<\/code> capability plus a dedicated nonce per screen (<code>iue_redeem_code_export_csv<\/code> \/ <code>iue_vip_code_export_csv<\/code>)<\/li>\n<\/ul><\/li>\n<li>Updated <code>.pot<\/code>\/<code>.po<\/code> translation files with the new strings introduced above (Vietnamese translation included); <code>.mo<\/code> not rebuilt as part of this change<\/li>\n<\/ul>\n\n<h4>1.6.0 \u2013 September 2, 2026<\/h4>\n\n<ul>\n<li>Added a new <strong>\"Require Login to Access Site\"<\/strong> option (Init User Engine \u2192 Settings \u2192 General). When enabled, visitors who are not logged in no longer see the site's actual content on any page\n\n<ul>\n<li>Instead, they see a blank page in the plugin's theme color with the built-in login modal opened automatically, so they can sign in without leaving the page<\/li>\n<li>Implemented via <code>template_redirect<\/code>, so <code>wp_head()<\/code>\/<code>wp_footer()<\/code> still run in full \u2014 the plugin's own login modal, and every other theme\/plugin hook attached to those actions, keeps working normally<\/li>\n<li>REST API, AJAX, cron, feed, and robots.txt requests are always excluded and are never blocked by this option<\/li>\n<li>Added filter <code>init_plugin_suite_user_engine_require_login_bypass<\/code> so other plugins\/themes can exclude specific requests (e.g. a payment callback URL) from the gate<\/li>\n<li>New dedicated <code>assets\/css\/require-login.css<\/code> and <code>assets\/js\/require-login.js<\/code> files render the gate's background and auto-open the login modal, kept separate from PHP output for coding-standards compliance<\/li>\n<\/ul><\/li>\n<li>Fixed: the frontend guest script (<code>guest.js<\/code>) only exposed <code>window.openLoginModal<\/code> (and wired up Escape-to-close, Alt+L, and hash-triggered opening) when an avatar element was present on the page. Pages without the avatar shortcode\/widget \u2014 including the new Require Login gate \u2014 could not open the login modal at all. The avatar element is now optional; the modal and its triggers work on any page as long as the modal itself is rendered (always the case via <code>wp_footer<\/code>)<\/li>\n<li>Updated <code>.pot<\/code>\/<code>.po<\/code> translation files with the new strings introduced above (Vietnamese translation included); <code>.mo<\/code> not rebuilt as part of this change<\/li>\n<\/ul>\n\n<h4>1.5.9 \u2013 August 29, 2026<\/h4>\n\n<ul>\n<li>Changed: \"Send Notification\" (Init User Engine \u2192 Send Notification) now uses a dedicated <strong>admin<\/strong> message type instead of reusing <strong>system<\/strong>, which was also used internally by several unrelated automated notices (VIP removed, redeem code success, VIP code success). Admin-sent notices and automated system notices are now cleanly separated\n\n<ul>\n<li>The \"System\" filter tab in the user-facing Inbox still includes admin-sent messages, same as before<\/li>\n<li>Previously sent messages (type <code>system<\/code>) are not migrated and keep displaying normally in the Inbox; only newly sent notifications use the new <code>admin<\/code> type<\/li>\n<\/ul><\/li>\n<li>Fixed: <strong>\"Pin this message\"<\/strong> on the Send Notification screen had no visible effect beyond storing a flag \u2014 pinned messages now always float to the top of the Inbox list, ahead of unpinned messages, across every filter tab<\/li>\n<li>Fixed: the <strong>\"Expire At\"<\/strong> field on Send Notification was saved to the database but never actually read back anywhere \u2014 it had no effect at all, on any message\n\n<ul>\n<li>Clarified and scoped its behavior to work together with the pin fix above: <strong>Expire At now only applies to pinned messages<\/strong> \u2014 once the time passes, the message is automatically unpinned (it remains fully visible in the Inbox as a regular message, nothing is hidden or deleted). Unpinned messages ignore this field entirely and never expire<\/li>\n<li>Added an hourly cron job (<code>init_plugin_suite_user_engine_unpin_expired_inbox<\/code>) that clears the <code>pinned<\/code> flag on messages past their <code>expire_at<\/code>; it only ever updates that one column, never deletes or alters message content<\/li>\n<li>Added inline descriptions on the Send Notification screen clarifying this scope for both the \"Pin this message\" checkbox and the \"Expire At\" field<\/li>\n<\/ul><\/li>\n<li>Fixed: the <strong>Date Range<\/strong> filter (Last 7\/30\/90 Days, All Time) on the Inbox Statistics page (Users \u2192 Init User Engine \u2192 Inbox Statistics) only affected the \"Daily Activity\" chart; every other number on the page (Total\/Unread\/Pinned Messages, Total Recipients, Message Types, Priority Levels, Top Recipients, Active Recipients, Peak Day) silently ignored it and always showed all-time (or hardcoded 30\/90-day) figures\n\n<ul>\n<li>All of the above now correctly scope to the selected range<\/li>\n<li>\"Active Recipients\" and \"Peak Day\" no longer use a hardcoded 30\/90-day window \u2014 they follow the selected range like everything else; label updated from \"Active Recipients (30d)\" to \"Active Recipients\" to match<\/li>\n<li>\"Sent Today\", \"This Week\", and \"This Month\" remain fixed calendar anchors by design, independent of the Date Range selector<\/li>\n<\/ul><\/li>\n<li>Added a short-lived (5 min) cache for the Inbox Statistics page, shared across all its stat sections, to avoid re-running its ~10 aggregate queries on every page load\/range change<\/li>\n<li>Added a database index on <code>created_at<\/code> for the inbox table to keep the now range-aware statistics queries fast on large tables. Applied automatically and safely via <code>dbDelta()<\/code> on next admin page load \u2014 existing data is untouched, no manual DB work or reinstall needed<\/li>\n<li>Updated <code>.pot<\/code>\/<code>.po<\/code> translation files for the above: added <code>admin<\/code> \/ <code>Active Recipients<\/code> \/ the two new Pin &amp; Expire At description strings, removed the now-unused <code>system<\/code> (as a standalone label) \/ <code>Active Recipients (30d)<\/code> strings, and corrected stale source-line references throughout<\/li>\n<\/ul>\n\n<h4>1.5.8 \u2013 August 22, 2026<\/h4>\n\n<ul>\n<li>Fixed: several user-facing notifications and REST API error messages ignored the admin-configured <strong>Coin Label<\/strong> \/ <strong>Cash Label<\/strong> and always displayed the hardcoded English words \"Coin\"\/\"Cash\" regardless of the custom label set in Settings \u2192 Currency Labels\n\n<ul>\n<li>Affected: level-up bonus notice, sign-up\/order\/review reward notices, all Coin \u21c4 Cash exchange error messages (invalid amount, min\/max limit, insufficient balance, zero-result, update failed), and VIP purchase error messages (wrong currency, insufficient balance)<\/li>\n<li>All of the above now consistently use the configured label, matching the behavior already used by Redeem Codes, Top-up, and the VIP purchase success message<\/li>\n<li>Added shared helpers <code>init_plugin_suite_user_engine_get_coin_label()<\/code> and <code>init_plugin_suite_user_engine_get_cash_label()<\/code> in <code>includes\/utils.php<\/code><\/li>\n<\/ul><\/li>\n<li>Fixed: frontend JS (<code>member.js<\/code>) referenced an <code>exchange_insufficient_coin<\/code> translation string for the Coin\u2192Cash exchange screen that was never localized from PHP, silently falling back to a hardcoded, non-translatable \"Not enough Coin.\" string; now properly localized and label-aware<\/li>\n<li>Removed a leftover duplicate\/dead array key in the frontend localization data (<code>exchange_insufficient<\/code>) that was immediately overwritten and never actually used<\/li>\n<li>Updated <code>.pot<\/code>\/<code>.po<\/code> translation files to match: merged duplicate Coin\/Cash message pairs into shared, label-aware strings; Vietnamese translation now consistently uses \"Coin\" instead of the previous literal \"xu\"\/\"\u0111\u1ed3ng xu\" wording throughout<\/li>\n<\/ul>\n\n<h4>1.5.7 \u2013 August 16, 2026<\/h4>\n\n<ul>\n<li>Added <strong>Date of Birth<\/strong> field to the frontend Edit Profile modal, stored per-user instead of a raw age number so it stays accurate over time without users needing to re-enter it\n\n<ul>\n<li>New REST field <code>dob<\/code> on both <code>GET \/profile\/me<\/code> and <code>POST \/profile\/update<\/code><\/li>\n<li>Server-side validation rejects malformed dates, future dates, and dates older than 120 years; invalid input is rejected before any other profile field is saved<\/li>\n<\/ul><\/li>\n<li>Added <code>init_plugin_suite_user_engine_get_age( $user_id )<\/code> helper \u2014 computes a user's current age from their stored date of birth, returns <code>0<\/code> if not set<\/li>\n<li>Added new i18n strings for the Date of Birth field and its validation messages<\/li>\n<\/ul>\n\n<h4>1.5.6 \u2013 August 16, 2026<\/h4>\n\n<ul>\n<li>Added <strong>VIP Codes<\/strong> \u2014 a dedicated code system for granting VIP membership days, alongside the existing Coin\/Cash Redeem Codes\n\n<ul>\n<li>New admin page (User Engine \u2192 VIP Codes) with the same workflow as Redeem Codes: single\/batch, multi-use, and user-locked codes, usage history, disable\/delete<\/li>\n<li>New REST endpoint <code>POST \/redeem-vip-code<\/code>, using the same transaction-locked, race-condition-safe redemption flow as Redeem Codes<\/li>\n<li>New \"Redeem VIP Code\" option in the frontend user dashboard, with its own modal<\/li>\n<\/ul><\/li>\n<li>Added <strong>Disable VIP Stacking<\/strong> setting\n\n<ul>\n<li>When enabled, a user with an active VIP can't purchase or redeem another VIP package\/code until the current one expires, instead of extending it<\/li>\n<li>Enforced consistently across both Coin\/Cash purchase and VIP Code redemption, with a row-level DB lock on redemption to prevent two simultaneous requests from both stacking VIP before either write completes<\/li>\n<\/ul><\/li>\n<li>Added <strong>Disable VIP Purchase<\/strong> setting\n\n<ul>\n<li>Completely turns off VIP purchasing\/activation for all users; hides the purchase UI and the \"Redeem VIP Code\" menu item, and blocks both the purchase and VIP Code redeem endpoints<\/li>\n<li>Existing active VIP members are unaffected \u2014 only new activations are blocked<\/li>\n<\/ul><\/li>\n<li>Changed: VIP Lifetime package now stores 99999 days instead of 9999 (previously only ~27 years, which confused users); all existing lifetime-detection logic remains compatible with old data<\/li>\n<li>Added new i18n strings for VIP Codes, VIP stacking, and VIP purchase-disabled notices<\/li>\n<\/ul>\n\n<h4>1.5.5 \u2013 August 11, 2026<\/h4>\n\n<ul>\n<li>Added <strong>Cloudflare Turnstile protection for WordPress's default forms<\/strong>\n\n<ul>\n<li>Extends the same Turnstile widget to WordPress's native Login, Registration, and Lost Password forms (<code>wp-login.php<\/code>), not just this plugin's own registration endpoint<\/li>\n<li>Three new toggles under Cloudflare Turnstile \u2192 Protect Default WordPress Forms: Login Form, Registration Form, Lost Password Form<\/li>\n<li>Login protection covers both the native <code>wp-login.php<\/code> page and the plugin's own login modal, since both submit through the same WordPress login flow<\/li>\n<li>Registration protection applies to WordPress's native <code>wp-login.php?action=register<\/code> page (only relevant when \"Anyone can register\" is enabled), independent from this plugin's own registration form\/endpoint<\/li>\n<li>All three require both Turnstile keys to be set and only take effect when \"Disable Captcha\" is off, same as the existing registration captcha<\/li>\n<li>Turnstile script for the login modal only loads once the modal is actually opened, matching the existing lazy-load behavior of the registration widget<\/li>\n<\/ul><\/li>\n<li>Added <strong>Test API button<\/strong> for Cloudflare Turnstile\n\n<ul>\n<li>Verifies the Secret Key against Cloudflare directly from the Settings page, before saving<\/li>\n<li>Site Key can only be fully confirmed once the widget actually renders in the browser (e.g. on the registration form)<\/li>\n<\/ul><\/li>\n<li>Added new i18n strings for the Turnstile form protection settings and the Test API button<\/li>\n<\/ul>\n\n<h4>1.5.4 \u2013 August 11, 2026<\/h4>\n\n<ul>\n<li>Fixed: Admin User Overview metabox (Recent Transactions \/ Recent EXP-related data) stopped showing new activity after the meta \u2192 custom table migration (v1.5.x). Root cause: the transaction\/EXP log reader queried the <strong>oldest<\/strong> 100 entries (<code>ORDER BY logged_at ASC LIMIT 100<\/code>) instead of the most recent ones, so entries logged after a user passed 100 total transactions never appeared. Now correctly fetches and displays the latest 100 entries<\/li>\n<li>Improved: Admin User Overview metabox now performs a single aggregate query for inbox stats (total \/ last 7 days \/ last message time) instead of 3 separate <code>COUNT<\/code>\/<code>MAX<\/code> queries, reducing database round-trips on profile page loads<\/li>\n<li>Improved: Minor cleanup of redundant array processing when rendering the Recent Transactions list<\/li>\n<li><code>Tested up to: 7.1<\/code><\/li>\n<\/ul>\n\n<h4>1.5.3 \u2013 July 29, 2026<\/h4>\n\n<ul>\n<li>Added <strong>two-way currency exchange<\/strong> between Cash and Coin\n\n<ul>\n<li>New REST endpoint <code>POST \/exchange-reverse<\/code> to convert Coin \u2192 Cash<\/li>\n<li>Exchange modal now supports toggling between Cash \u2192 Coin and Coin \u2192 Cash<\/li>\n<li>Added independent exchange rate settings for both directions<\/li>\n<li>Rate limiting, idempotency, and mutex locks applied to both endpoints<\/li>\n<\/ul><\/li>\n<li>Added <strong>VIP bonus for Cash<\/strong>\n\n<ul>\n<li>VIP users now receive configurable bonus Cash (%) on all Cash additions<\/li>\n<li>Aligns with existing VIP bonus behavior for Coin and EXP<\/li>\n<\/ul><\/li>\n<li>Added <strong>VIP purchase by Cash<\/strong>\n\n<ul>\n<li>VIP packages can now be priced and purchased using Cash instead of Coin<\/li>\n<li>New setting to choose payment currency: Coin only, Cash only, or Both<\/li>\n<li>When set to Both, users can toggle between Coin and Cash in the purchase modal<\/li>\n<li>VIP purchase log now records the currency used for each transaction<\/li>\n<\/ul><\/li>\n<li>Added new i18n strings for exchange direction, VIP currency selection, and Cash-related notifications<\/li>\n<\/ul>\n\n<h4>1.5.2 \u2013 May 17, 2026<\/h4>\n\n<ul>\n<li>Updated custom dashicon CSS to use <code>currentColor<\/code> for full compatibility with WordPress Administration Color Schemes<\/li>\n<li>Removed hardcoded icon colors that conflicted with theme-aware color variables<\/li>\n<li>Ensured compatibility with WordPress 7.0's updated admin color system<\/li>\n<\/ul>\n\n<h4>1.5.1 \u2013 April 22, 2026<\/h4>\n\n<ul>\n<li>Refactored migration architecture to use self-looping WP-Cron instead of admin_init execution<\/li>\n<li>Introduced background migration runner (<code>init_plugin_suite_iue_migration_event<\/code>) with automatic rescheduling<\/li>\n<li>Added transient-based locking mechanism to prevent concurrent migration execution<\/li>\n<li>Migration process is now fully decoupled from admin traffic and runs reliably in low-traffic environments<\/li>\n<li>Improved stability and consistency of batch migration for large datasets<\/li>\n<li>Activation hook now schedules migration automatically if not already completed<\/li>\n<li>Maintained full backward compatibility with existing migration logic and data structures<\/li>\n<\/ul>\n\n<h4>1.5.0 \u2013 April 21, 2026<\/h4>\n\n<ul>\n<li>Migrated transaction log (coin\/cash) and EXP log from user meta to dedicated database tables<\/li>\n<li>Introduced <code>init_user_engine_transaction_log<\/code> and <code>init_user_engine_exp_log<\/code> tables for better scalability<\/li>\n<li>Automatic data migration from old user meta (<code>iue_coin_cash_log<\/code>, <code>iue_exp_log<\/code>) with cleanup on completion<\/li>\n<li>Migration runs in batches of 200 users to prevent timeouts on large sites and resumes if interrupted<\/li>\n<li>REST API pagination for transaction and EXP history now uses true COUNT + OFFSET instead of loading all records<\/li>\n<li>Added <code>wp_cache<\/code> support for transaction and EXP log reads with automatic invalidation on write<\/li>\n<li>Database schema check is now version-gated to avoid redundant queries on every admin load<\/li>\n<li>Schema and migration are also triggered via <code>upgrader_process_complete<\/code> for reliable update handling<\/li>\n<li>Full backward compatibility maintained: all hooks, filters, and i18n strings are preserved<\/li>\n<\/ul>\n\n<h4>1.4.9 \u2013 April 15, 2026<\/h4>\n\n<ul>\n<li>Added filter to override theme color system (theme_color, theme_active_color)<\/li>\n<li>Introduced centralized color hook for easier customization from themes and addons<\/li>\n<li>Ensured safe fallback when filter returns incomplete or invalid values<\/li>\n<\/ul>\n\n<h4>1.4.8 \u2013 March 25, 2026<\/h4>\n\n<ul>\n<li>Fixed check-in countdown not starting on new devices after login<\/li>\n<li>Countdown now resets to full duration on unrecognized devices<\/li>\n<li>Remaining time is saved only on tab hide and page unload, not every second<\/li>\n<li>Fixed date comparison using locale-aware format to prevent UTC offset mismatch<\/li>\n<\/ul>\n\n<h4>1.4.7 \u2013 March 24, 2026<\/h4>\n\n<ul>\n<li>Added wp_cache support for unread Inbox count<\/li>\n<li>Reduced database load by caching COUNT(*) queries per user<\/li>\n<li>Cache is automatically cleared on insert, read, delete, and bulk operations<\/li>\n<li>Introduced centralized cache helpers and consistent naming<\/li>\n<li>Improved performance and internal code structure for better maintainability<\/li>\n<\/ul>\n\n<h4>1.4.6 \u2013 February 7, 2026<\/h4>\n\n<ul>\n<li>Fixed redeem code generation logic to respect custom codes<\/li>\n<li>Single-use codes now preserve exact input when quantity is 1<\/li>\n<li>Prefix + random suffix only applies to batch generation (qty &gt; 1)<\/li>\n<li>Multi-use and locked codes no longer force random suffixes<\/li>\n<\/ul>\n\n<h4>1.4.5 \u2013 February 4, 2026<\/h4>\n\n<ul>\n<li>Fixed Inbox pagination not respecting the active filter<\/li>\n<li>Total message count and total pages are now calculated per category<\/li>\n<li>Prevents incorrect page numbers when switching between filters<\/li>\n<li>Ensures accurate server-side pagination and consistent navigation<\/li>\n<\/ul>\n\n<h4>1.4.4 \u2013 February 4, 2026<\/h4>\n\n<ul>\n<li>Added bulk generation for single-use redeem codes\n\n<ul>\n<li>Supports quantity-based creation with automatic prefix usage<\/li>\n<li>Generates random 6-character suffix using <code>wp_generate_password()<\/code><\/li>\n<li>When quantity = 1, uses the exact input code (no random suffix appended)<\/li>\n<\/ul><\/li>\n<li>Added safe delete action for redeem codes (only unused codes can be removed)<\/li>\n<li>Improved redeem code creation flow with better validation, sanitization, and consistent behavior across modes<\/li>\n<li>Upgraded Inbox system with categorized filters\n\n<ul>\n<li>Added filters: All, Unread, System, Rewards, Activity, Other<\/li>\n<li>Server-side filtering with correct pagination<\/li>\n<li>Logical grouping of message types for cleaner UX<\/li>\n<\/ul><\/li>\n<li>Minor UI and internal refinements for consistency and maintainability<\/li>\n<\/ul>\n\n<h4>1.4.3 \u2013 January 28, 2026<\/h4>\n\n<ul>\n<li>Added VIP state\u2013aware body classes for frontend customization\n\n<ul>\n<li>Automatically adds <code>iue-vip<\/code> for active VIP users<\/li>\n<li>Adds <code>iue-vip-expired<\/code> for users whose VIP has expired<\/li>\n<li>Adds <code>iue-expire-soon<\/code> when VIP is close to expiration (default: \u2264 1 day)<\/li>\n<\/ul><\/li>\n<li>Introduced extensibility hooks for VIP presentation logic\n\n<ul>\n<li>New filter <code>init_plugin_suite_user_engine_vip_expire_soon_threshold<\/code> to customize the \u201cexpire soon\u201d window<\/li>\n<li>New filter <code>init_plugin_suite_user_engine_body_vip_classes<\/code> to allow developers to add or modify VIP-related body classes<\/li>\n<\/ul><\/li>\n<li>Improved separation between VIP core logic and UI layer\n\n<ul>\n<li>Enables lightweight CSS-based customization without conditional checks<\/li>\n<li>Keeps VIP business logic isolated and stable<\/li>\n<\/ul><\/li>\n<li>Minor internal refinement for consistency and long-term maintainability<\/li>\n<\/ul>\n\n<h4>1.4.2 \u2013 November 19, 2025<\/h4>\n\n<ul>\n<li>Updated <strong>transaction logging system<\/strong> for Coin &amp; Cash\n\n<ul>\n<li>VIP users now automatically receive the correct <strong>bonus %<\/strong> directly inside the log entry<\/li>\n<li>Log entries now include:<\/li>\n<li><code>original<\/code> (amount before bonus)<\/li>\n<li><code>amount<\/code> (amount after bonus)<\/li>\n<li><code>vip_bonus<\/code> flag and <code>bonus_percent<\/code> value<\/li>\n<li>Ensures perfectly aligned behavior with <code>init_plugin_suite_user_engine_add_coin()<\/code><\/li>\n<\/ul><\/li>\n<li>Improved accuracy of VIP-related operations\n\n<ul>\n<li>Bonus only applies to <strong>Coin<\/strong> and only when <strong>adding<\/strong> (no bonus for deductions)<\/li>\n<li>Avoids mismatch between displayed history and real balance changes<\/li>\n<\/ul><\/li>\n<li>Enhanced internal data consistency\n\n<ul>\n<li>Log entries capped at 100 items with stable array slicing<\/li>\n<li>Ensures clean, lightweight meta storage over long-term usage<\/li>\n<\/ul><\/li>\n<li>Minor structural refinement for better readability and maintainable code paths<\/li>\n<\/ul>\n\n<h4>1.4.1 \u2013 November 17, 2025<\/h4>\n\n<ul>\n<li>Fixed VIP bonus logic when modifying Coin balance\n\n<ul>\n<li>Bonus percentage now applies <strong>only when adding<\/strong> positive Coin amounts<\/li>\n<li>Negative adjustments (deducting Coin) <strong>no longer receive bonus<\/strong><\/li>\n<\/ul><\/li>\n<li>Added support for <code>data-iue=\"register\"<\/code>\n\n<ul>\n<li>Automatically opens the modal <strong>and switches directly to the Register tab<\/strong><\/li>\n<li>Ignores custom register URL mode (only toggles modal when active)<\/li>\n<\/ul><\/li>\n<li>Improved WPCS compatibility\n\n<ul>\n<li>Added targeted <code>phpcs:ignore<\/code> rules for PluginCheck false positives<\/li>\n<li>Clean handling of dynamic table names in prepared SQL queries<\/li>\n<\/ul><\/li>\n<li>No other changes; fast patch release for immediate correctness<\/li>\n<\/ul>\n\n<h4>1.4.0 \u2013 November 4, 2025<\/h4>\n\n<ul>\n<li>Improved <strong>Admin User Overview<\/strong> security model\n\n<ul>\n<li>Any user can view their own overview (Coin, Cash, Level, VIP info, Inbox)<\/li>\n<li>Action buttons (Remove VIP \/ Toggle Avatar Upload Ban \/ Inbox Statistics) are now restricted to administrators only<\/li>\n<li>UI gracefully disables restricted actions for non-admin users instead of hiding them<\/li>\n<\/ul><\/li>\n<li>Added server-side permission guards for sensitive actions\n\n<ul>\n<li><code>iue_remove_vip<\/code> and <code>iue_toggle_avatar_ban<\/code> now require <code>manage_options<\/code><\/li>\n<li>Requests are validated using capability check + nonce verification<\/li>\n<li>Prevents URL\/REST crafting or manual calls to admin-post endpoints<\/li>\n<\/ul><\/li>\n<li>Improved admin notices behavior\n\n<ul>\n<li>Success\/error messages only appear for administrators<\/li>\n<li>Notices limited to <code>profile.php<\/code> and <code>user-edit.php<\/code> screens<\/li>\n<\/ul><\/li>\n<li>Minor code cleanup and consistency improvements to maintainable structure<\/li>\n<\/ul>\n\n<p>View full changelog (all versions): <a href=\"https:\/\/en.inithtml.com\/plugin\/init-user-engine\/\">Init User Engine \u2013 Changelog<\/a><\/p>","raw_excerpt":"Gamified user engine with EXP levels, Coin\/Cash wallet, check-in, VIP, inbox, and referral \u2013 powered by REST API and Vanilla JS.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/oci.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/240696","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/oci.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/oci.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/oci.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=240696"}],"author":[{"embeddable":true,"href":"https:\/\/oci.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/brokensmile2103-1"}],"wp:attachment":[{"href":"https:\/\/oci.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=240696"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/oci.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=240696"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/oci.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=240696"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/oci.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=240696"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/oci.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=240696"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/oci.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=240696"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}