Development

How to Protect Paid Downloads With WishList Member

WishList Member can protect individual WordPress media files or entire membership-level folders. The important part is testing the file itself, not only the page that links to it. A protected sales page with a publicly reachable PDF URL is not a protected download.

Disclosure: I work for Caseproof, the company that owns WishList Member, and I was the product's original programmer. This tutorial is based on the public product documentation.

Choose file or folder protection

Use file protection when downloads already live in the WordPress Media Library or when individual files need different access rules. Each file can be protected, unprotected, or set to inherit the protection state of the page or post where it appears.

Use folder protection when you maintain a collection of files for one or more membership levels and want to upload them to an assigned folder. WishList Member can create protected folders for membership levels and can force downloads rather than letting the browser display supported file types.

The official guides cover the current file-protection settings and folder-protection settings. Confirm the current product UI and server instructions before configuring a production site.

Design the access model first

Write a simple matrix before uploading anything:

DownloadFreeSilverGoldExpired
Starter guideAllowAllowAllowDeny
Template libraryDenyAllowAllowDeny
Private workshop archiveDenyDenyAllowDeny

Decide whether canceled members retain access until the paid-through date, whether paused subscriptions behave differently, and whether administrators receive access for support. Those are membership rules, not file-system details.

Avoid using one broad level merely because it is convenient. Grant the minimum access the product promises and test level combinations if members can belong to more than one.

Protect a Media Library file

The current file workflow is:

  1. Upload the file through the WordPress Media Library.
  2. Open WishList Member's Content Protection area and enable the Files section.
  3. Locate the uploaded file.
  4. Set its status to Protected.
  5. Add the membership levels that may access it.
  6. Place the file link on the protected member page.

An Inherited status follows the page or post protection state. That can be useful, but explicit file protection is easier to audit for a paid download that appears in several places.

Review the File Protection Ignore List. Image, CSS, and JavaScript extensions are commonly ignored because themes need them publicly, but your paid asset type must not be excluded. Do not remove required public asset types casually because doing so can break page rendering.

Protect a folder of downloads

WishList Member's folder protection uses a parent folder in the WordPress installation, with level-specific subfolders. The public documentation currently describes a default parent named files and automatic folder creation for membership levels.

A practical workflow is:

  1. Confirm Folder Protection is enabled.
  2. Confirm the parent path and server configuration.
  3. Create or select the folder.
  4. Set the folder to Protected.
  5. Add every level that should access its contents.
  6. Upload files to that specific folder.
  7. Enable Force Download if that is the intended browser behavior.

Changing a membership level's display name does not necessarily rename an existing folder. Treat folder paths as stable infrastructure once customers have links.

Configure the web server and cache

Protection must operate at the path where the web server serves the file. Nginx, managed WordPress hosts, reverse proxies, and CDNs may need explicit rules.

Follow WishList Member's current Nginx instructions when applicable. On managed hosting, share the vendor's documented path and cache exclusions with support rather than inventing a generic rewrite.

A cache must not store an authorized file response and replay it to a later unauthorized request. Exclude protected file paths from full-page caching and CDN caching unless the delivery layer varies safely by authorization and uses private responses.

After any cache change, purge existing entries. A corrected rule does not remove an already cached public object automatically.

Link to the managed file

Use the link generated or managed by WordPress and WishList Member. Do not also upload the same paid file to a public CDN bucket, theme directory, page-builder asset folder, or email-service attachment.

If the file already circulated at an unprotected URL, protecting a new copy does not revoke the old URL. Remove or deny the old object, purge caches, update links, and verify that search engines or public archives did not index it.

Download URLs are access paths, not secrets. Assume a member can copy and share one, then ensure the server performs the membership check on every request.

Test the complete access matrix

Use a private browser window and dedicated test accounts. Test the exact download URL, not only the button.

For each protected asset, verify:

  • An anonymous visitor is denied or redirected as configured.
  • An active authorized member can download the correct file.
  • An active member without the assigned level is denied.
  • An expired or canceled member is handled according to the paid-through rule.
  • A direct pasted URL cannot bypass protection.
  • A new request after logout is denied and a shared cache never discloses another member's response.
  • A copied link behaves correctly in a different browser.
  • Administrators get only the intended support behavior.
  • Range requests and download managers do not bypass access checks.
  • The response has the intended filename and content type.

Run the tests through the production-like web server. PHP's local server cannot prove that Nginx, Apache, a CDN, or managed-host cache rules are correct.

These checks prove enforcement for new requests. They cannot recall bytes that an authorized member already downloaded, saved, or copied while access was valid.

Test membership transitions

File access changes when membership state changes. Create repeatable tests for:

  • New purchase or manual level assignment
  • Renewal
  • Upgrade and downgrade
  • Cancellation before the access end date
  • Expiration
  • Refund or revocation
  • Removal from one of several levels

Confirm both the membership record and the actual file response. An administration screen can show the expected level while stale cache or an old delivery URL still exposes the file.

Protect the surrounding workflow

File protection does not prevent an authorized member from saving and sharing a downloaded file. For highly sensitive documents, consider individualized watermarking, short-lived signed delivery, download limits, or a viewer that avoids distributing the source file. Each option adds complexity and still cannot guarantee that a determined authorized viewer will not capture the content.

Use clear filenames without private customer information. Keep source files and backups outside publicly served directories. Scan uploads for malware when contributors can upload content.

Collect only the download logs you need. IP addresses and user-agent strings may be personal data, so apply an appropriate retention policy and access control.

Troubleshoot in layers

If protection fails, check in this order:

  1. Is the correct file or folder listed in WishList Member?
  2. Is its status Protected rather than Unprotected or unexpectedly Inherited?
  3. Is the test member assigned to an allowed active level?
  4. Is the page linking to the same managed URL you tested?
  5. Is the file extension on the ignore list?
  6. Does the web server use the required protection rules?
  7. Is a host or CDN cache serving an older response?
  8. Does another plugin rewrite or offload media URLs?
  9. Is an old public copy still reachable elsewhere?

Change one layer at a time and repeat the same direct request in a private session.

Review WishList Member's current file-protection documentation before rollout, then have a second person test anonymous, authorized, unauthorized, expired, and direct-link access. Paid download protection is complete only when the file request itself enforces the membership rule.