Members Area & Paid Content (dfmembership) — Complete guide
Install, configure and run a members area and paid gated content: plans mapped to customer groups, limited-duration access (cron) or recurring subscription (Stripe), library with paywall and SEO schema for PrestaShop 8 and 9.
Overview
The Members Area & Paid Content module (dfmembership) turns your shop into a membership platform: you sell subscriptions that unlock a members area and gated content (articles, videos, files, links), group pricing, or private CMS pages. Each plan is tied to a native PrestaShop customer group, so the shop handles catalog visibility and group prices natively; the module adds billing, the paywall, the library, automatic expiry and group synchronisation on top.
Two business models are available from the very first version and are chosen per plan: limited-duration access (the customer pays once for N days, access expires automatically) and a real recurring subscription via Stripe Billing (renewal and cancellation driven by webhooks).
Compatibility
- PrestaShop 8.0 to 9.x
- PHP 7.4 to 8.3
- Single-shop and multistore
- 5 languages: FR, EN, ES, DE, IT
- Classic theme and custom themes
- No dependency: no Composer, no bundled Stripe SDK (native cURL API calls)
Key concepts
A plan equals a customer group
A plan represents a membership tier (for example “Premium” or “Pro annual”). Each plan is mapped to a PrestaShop customer group: when a customer becomes a member, they are added to that group; when their subscription expires or is cancelled, they are removed from it. You therefore inherit all of PrestaShop’s native mechanics: group-specific prices, carrier restrictions, category visibility and more — with no extra configuration in the module.
First create your customer groups in Customers > Groups, then map them to your plans. The same group can power your group prices and your content gating.
The two billing modes
- Limited duration: the customer pays once and gets access for the plan’s length (in days). A cron task expires access once the term is reached. Ideal for a one-off pass, a seasonal access or time-limited content. On early renewal, remaining time is stacked.
- Stripe subscription: a real recurring subscription managed by Stripe Billing. Renewal, payment failure and cancellation are received through webhooks and reflected automatically on the customer’s access. Ideal for recurring revenue (MRR).
Installation
- In the back office, open Modules > Module Manager.
- Click Upload a module and select the
dfmembership.zipfile. - Once installed, click Configure.
On install, the module creates its tables (plans, subscriptions, content), registers its hooks, generates a random cron token and adds a Membership menu under Sell, with three sub-tabs: Plans, Subscriptions and Content. A My membership link appears in the customer account.
General configuration
The module’s configuration page gathers the global settings as well as the two integration URLs (Stripe webhook and cron) to copy into your external tools.
Stripe settings
- Stripe secret key: your
sk_live_…key (orsk_test_…in test mode). Required for recurring billing. - Stripe publishable key: your
pk_…key. - Webhook signing secret: the
whsec_…value Stripe provides for the endpoint. It is used to verify the signature of every incoming webhook.
Content and paywall
- Protected CMS pages: the comma-separated list of CMS page ids reserved for members (for example
4,7,9). Non-members trying to open them are redirected to the library. - Paywall SEO schema: injects
isAccessibleForFreeset to false structured data on gated content, so it stays indexable by Google without being treated as cloaking. - Teaser length (words): number of words shown before the paywall when no explicit teaser is set on a content item.
- Regenerate cron token: replaces the token in the cron URL (useful if it leaked).
The secret key and webhook secret are sensitive. Use the test keys while validating the flow, then switch to the live keys in production. Never share the cron URL with its token publicly.
Creating a plan
In Membership > Plans, add a tier and fill in:
- Name, tagline, description (multilingual): shown on the subscribe page and the home block.
- Billing mode: “Limited-duration access (cron)” or “Recurring subscription (Stripe)”.
- Price: the amount shown to the customer.
- Duration (days): the access length in limited-duration mode.
- Trial (days): an optional trial period (0 = none). In Stripe mode, the trial is passed to the Stripe subscription.
- Stripe Price ID: the
price_…id of the recurring price created in Stripe (Stripe mode only). - Mapped customer group: the group the member is placed in while their access is active.
- Position and Active: display order and availability of the plan.
Limited-duration mode and cron
In duration mode, the subscription is created and then activated for the plan’s length; its end date is computed from the activation date. Free plans (zero price) are activated immediately, and a plan with a trial first opens a trial window.
To automatically close access once the term is reached, schedule the cron URL shown in the configuration (token-protected). A daily run is enough:
curl "https://your-shop/index.php?fc=module&module=dfmembership&controller=cron&token=YOUR_TOKEN"
The cron sets any duration subscription whose end date has passed to “expired”, then resynchronises the groups of the affected customer. Without the cron, access does not expire on its own: remember to schedule it.
Stripe subscription mode
In Stripe mode, the customer is redirected to a Stripe Checkout page in subscription mode. When the payment completes, Stripe notifies your shop via webhook and access is activated. The full lifecycle is then driven by Stripe.
Setup
- In Stripe, create a product and a recurring price (monthly, yearly…), then copy its
price_…into the matching plan. - Fill in your Stripe keys and the webhook secret in the module configuration.
- In Stripe, add a webhook endpoint pointing to the URL shown in the configuration, and subscribe it to the events:
checkout.session.completed,invoice.paid,invoice.payment_failed,customer.subscription.updatedandcustomer.subscription.deleted.
What the webhooks do
- checkout.session.completed: activates the subscription and stores the Stripe subscription id.
- invoice.paid: renews access and rolls the period end date forward.
- invoice.payment_failed: keeps access during the dunning grace period handled by Stripe.
- customer.subscription.updated: reflects a cancellation scheduled at period end or a date change.
- customer.subscription.deleted: closes access for good and removes the customer from their group.
Every webhook is signature-verified using the whsec_… secret. If the signature is invalid or the secret is empty, the request is rejected. Check this setting first if subscriptions are not activating.
Content library and paywall
In Membership > Content, create the gated items. Each content item has:
- Type: article, video, file or link.
- Title, teaser, content (multilingual). The teaser is the public preview shown before the paywall; left empty, it is auto-generated from the first words of the content (adjustable length).
- Media URL: the video embed, the downloadable file or the external link.
- Required plan: the plan that grants access to the content. The value “Any active member” opens the content to any ongoing subscription.
- Drip delay (days): number of days after the subscription start before the content unlocks, to release a library progressively (drip content).
On the storefront, the library lists items with their teaser. A member sees the full content; a visitor or a non-member sees the teaser then a paywall inviting them to subscribe. Access control combines the required plan and the drip delay.
SEO for gated content
When the SEO schema option is on, the module adds structured data on unlocked content indicating that it is paid content (Google’s flexible sampling). The reserved block is marked with a dedicated CSS class, which lets Google index the page without penalising the difference between what the crawler and the member see.
Reserved CMS pages
To reserve existing CMS pages (a resources page, a private area…), enter their ids in Protected CMS pages. A non-member opening one of these pages is automatically redirected to the library, where they can discover the plans. Members access them normally.
Members area
From My account > My membership, the customer finds their ongoing subscriptions: plan, status, billing mode, renewal or end date. They can open the library and, where relevant, cancel a subscription. Cancellation happens at period end: access stays open until the already-paid term, then closes. In Stripe mode, the request is forwarded to Stripe; in duration mode, access is simply not renewed.
Managing subscriptions (back office)
In Membership > Subscriptions, you see every subscription (customer, email, plan, status, mode, dates) with search and export. The detail view lets you force a status (active, expired, cancelled) when needed: a goodwill gesture, a fix, a dispute. Any status change immediately resynchronises the customer’s group.
Groups are also resynchronised on customer login and on order validation, to guarantee that access always reflects the genuinely active subscriptions.
Going further
The billing architecture is extensible: a new provider (for example recurring PayPal) is added by implementing the BillingManagerInterface from the src/Billing/ folder and registering it in the BillingManagerFactory, without touching the rest of the module. Possible evolutions include: AI-generated teasers, dunning emails, gift memberships, plan changes with proration, or an MRR / churn dashboard.
FAQ and troubleshooting
A customer paid but has no access
In Stripe mode, first check the webhook secret and that the endpoint is indeed receiving events in the Stripe dashboard (Webhooks tab). Activation depends on the checkout.session.completed event. In duration mode, check that the subscription has turned active; you can force it from the detail view.
Access never expires
Duration mode relies on the cron. Make sure you have scheduled the cron URL (daily) with the correct token. You can call it manually to test: the JSON response shows the number of expired subscriptions.
How do I link a plan to reduced prices?
Map the plan to a customer group, then set specific prices for that group on your product pages (or via a catalog price rule). As long as the member is active, they belong to the group and benefit from those prices automatically.
Is gated content indexable by Google?
Yes, if the SEO schema option is on: paid content is flagged as such via structured data, which matches Google’s guidance on flexible sampling. You keep indexing without hiding the paid nature.
Can I offer a free trial?
Yes. Set a number of trial days on the plan. In duration mode, a trial window is opened; in Stripe mode, the trial is passed to the Stripe subscription (trial_period_days).
Is PayPal supported?
Version 1 implements the duration and Stripe modes. Recurring PayPal can be added thanks to the extensible billing interface, with no module rewrite.
Is it PrestaShop 9 compatible?
Yes. The module is compatible with PrestaShop 8 and 9, in multistore and multilingual setups (FR, EN, ES, DE, IT).