ساخت یک مودال جستجو برای سایت‌های وردپرسی دارای محدودیت دسترسی (Membership-Gated)

بیشتر آموزش‌های جستجوی وردپرس پس از اضافه کردن یک ویجت به هدر متوقف می‌شوند.

این روش زمانی که محتوای محدود شده‌ای مانند دوره‌های پولی یا ویدیوهای خصوصی دارید، کارایی ندارد. یک جستجوی پیش‌فرض، عناوین مطالب خصوصی شما را برای بازدیدکنندگان وارد نشده (logged-out) فاش می‌کند.

من یک مودال جستجوی زنده برای یک سایت عضویت تناسب اندام ساختم. این سایت از WordPress، WooCommerce، Divi، LearnDash و WishList Member استفاده می‌کند.

در اینجا نحوه ساخت جستجویی که به دیوار پرداخت (paywall) شما احترام می‌گذارد، آورده شده است.

معماری

من از یک ایندکس واحد با فیلترینگ آگاه از سطح دسترسی استفاده کردم. این انتخاب را برای اطمینان از اینکه کاربر وارد نشده هرگز عنوان یا گزیده‌ای از پست‌های مخصوص اعضا را نبیند، انجام دادم.

رابط کاربری (UI) از آیکونی استفاده می‌کند که یک لایه تمام‌صفحه (overlay) را باز می‌کند. این کار باعث صرفه‌جویی در فضای موبایل می‌شود و نسبت به یک نوار ورودی فشرده، ظاهر تمیزتری دارد.

بخش بک‌اند (Backend)

همه چیز از طریق یک مسیر REST سفارشی واحد در یک child theme اجرا می‌شود.

قوانین فنی کلیدی:

  • محافظت از وابستگی‌ها (Guard dependencies): برای پلاگین‌های جستجو مانند Relevanssi از یک بررسی تابعی استفاده کنید. اگر پلاگین موجود نبود، جستجو باید به جای از کار انداختن سایت، به هسته WordPress بازگردد (fallback).
  • فیلترینگ سمت سرور (Server-side filtering): هرگز نتایج را با استفاده از JavaScript فیلتر نکنید. اگر نتیجه‌ای را در مرورگر مخفی کنید، داده‌ها از قبل در پاسخ شبکه (network response) وجود دارند. هر کسی با DevTools می‌تواند آن‌ها را ببیند. داده‌ها را قبل از اینکه سرور پاسخ را ارسال کند، فیلتر کنید.
  • استثنا کردن از کش (Cache exclusion): شما باید مسیر REST جستجوی خود را از کش صفحات (page caching) مستثنی کنید. اگر نتایج را کش کنید، ممکن است جستجوی یک عضو به یک مهمان ارائه شود و محتوای خصوصی فاش گردد.

بخش فرانت‌اند (Frontend)

سمت کلاینت از vanilla JavaScript استفاده می‌کند.

سه مورد باعث بهبود تجربه کاربری (UX) می‌شوند:

  • Debounce: پس از هر کلید، ۲۵۰ میلی‌ثانیه صبر کنید و سپس درخواست را ارسال کنید. این کار از بار اضافی و غیرضروری به سرور جلوگیری می‌کند.
  • AbortController: وقتی کاربر به تایپ کردن ادامه می‌دهد، درخواست‌های قبلی را لغو کنید. این کار از بازنویسی نتایج جدید توسط نتایج قدیمی جلوگیری می‌کند.
  • حالت‌های خطا (Error states): اگر fetch با شکست مواجه شد، یک پیام واضح نشان دهید. یک لودر چرخان که هرگز متوقف نمی‌شود، تجربه کاربری بدی است.

درس موبایل

من سعی کردم دکمه جستجو را به منوی موبایل Divi تزریق (inject) کنم. قالب کلیک‌ها را رهگیری می‌کرد و باعث می‌شد دکمه غیرقابل کلیک شود.

راه حل ساده بود: با قالب نجنگید.

به جای قرار دادن دکمه داخل منو، آن را به عنوان یک عنصر مستقل در هدر تزریق کردم. این کار باعث شد دکمه خارج از کنترل قالب باقی بماند و لمس کردن آن آسان شود.

خلاصه

  • کنترل دسترسی باید در سمت سرور انجام شود.
  • نقاط انتهایی (endpoints) جستجو را از کش خود مستثنی کنید.
  • از debounce و AbortController برای مدیریت درخواست‌ها استفاده کنید.
  • برای جلوگیری از XSS، تمام داده‌های API را قبل از تزریق به DOM، Escape کنید.
  • اگر یک صفحه‌ساز (page builder) در برابر کد شما مقاومت کرد، عنصر خود را به جای داخل آن، در کنار آن قرار دهید.

منبع: https://dev.to/highcenburg/building-a-search-modal-for-a-membership-gated-wordpress-site-b92