How I Locked My 4K Downloads Behind Patreon — Without a Plugin
After 2 full days of testing, I figured out a smart workaround to lock 4K video downloads behind Patreon using just:
One hidden page
A few lines of HTML + JavaScript
3 small PHP files
No bloated plugin, and best of all — **the 4K link is not exposed in the source code. Obviously for me this was useful for a button, but you can hide anything by simply having a class id if you are using Elementor, you can hide certain sections if needed. Hope this helps someone!
Step 1: Create a “Patreon Access Check” Page
On a hidden page (set to private or visible only to patrons), inject this:
html
<!-- This div is shown only if user has access -->
<div id="patreon-access" data-access="true" style="display:none;"></div>
If the user doesn’t have access, the element won’t render — and we use that in step 2.
Step 2: Add This to functions.php
To get the current post ID into your HTML via a shortcode:
add_shortcode('post_id', function () {
return get_the_ID();
});
Step 3: Add This HTML to Your Page
Paste this into an Elementor HTML widget or any page editor:
<iframe id="patreon-check-frame" src="https://yourwebsite.com/patreon-check/" style="display:none;" onload="checkPatreonAccess()"></iframe>
<div id="acf-4k-link" data-post="[post_id]" style="display:none;"></div>
<div id="4k-button-container">
<a class="button button-4k-download" style="display:none;" download>🎉 Download 4K</a>
<div class="button button-4k-not-available" style="display:none;">🚫 4K Not Available</div>
<a href="https://patreon.com/YOURPATREON" class="button button-upgrade-patreon" target="_blank" style="display:none;">🔒 Unlock 4K Access</a>
</div>
<script>
function checkPatreonAccess() {
setTimeout(() => {
try {
const iframeDoc = document.getElementById('patreon-check-frame').contentWindow.document;
const accessEl = iframeDoc.querySelector('#patreon-access');
if (accessEl?.dataset.access === "true") {
fetch('/wp-content/themes/YOUR-CHILD-THEME/set-session.php')
.then(() => {
const postId = document.getElementById('acf-4k-link').dataset.post;
fetch(`/wp-content/themes/YOUR-CHILD-THEME/check-4k.php?post_id=${postId}`)
.then(res => res.json())
.then(data => {
if (data.has_4k) {
const btn = document.querySelector('.button-4k-download');
btn.href = `/wp-content/themes/YOUR-CHILD-THEME/secure-download.php?post_id=${postId}`;
btn.style.display = 'inline-block';
} else {
document.querySelector('.button-4k-not-available').style.display = 'inline-block';
}
});
});
} else {
document.querySelector('.button-upgrade-patreon').style.display = 'inline-block';
}
} catch (e) {
console.warn("Access check failed:", e);
}
}, 500);
}
</script>
Step 4: secure-download.php
Create this file at:
/wp-content/themes/hello-theme-child-master/secure-download.php
php
CopyEdit
<?php
require_once($_SERVER['DOCUMENT_ROOT'].'/wp-load.php');
session_start();
$post_id = intval($_GET['post_id'] ?? 0);
if (!$post_id) wp_die('Missing post ID.');
if (!is_user_logged_in()) wp_die('You must be logged in.');
if ($_SESSION['patreon_access'] !== true) wp_die('Access denied.');
$video_url = get_field('4k_video_url', $post_id);
if (!$video_url) wp_die('4K video not found.');
wp_redirect($video_url);
exit;
Step 5: set-session.php
/wp-content/themes/hello-theme-child-master/set-session.php
<?php
session_start();
$_SESSION['patreon_access'] = true;
Step 6: check-4k.php
/wp-content/themes/hello-theme-child-master/check-4k.php
php
CopyEdit
<?php
require_once($_SERVER['DOCUMENT_ROOT'].'/wp-load.php');
$post_id = intval($_GET['post_id'] ?? 0);
$has_4k = get_field('4k_video_url', $post_id) ? true : false;
echo json_encode(['has_4k' => $has_4k]);
Final Result
Button only shows if user is a Patron
4K link is hidden behind a secure PHP redirect
If no link: “4K Not Available”
If not a Patron: shows “Unlock on Patreon”