# Email-Gated Download Form

> Adds a [wpide_gated_download] shortcode that asks for an email address before a guide or PDF can be downloaded, then emails a private download link valid for 48 hours.

- Type: PHP
- Runs: Run everywhere
- Category: [Forms](https://wpide.com/library/category/forms/)
- Tags: lead-magnet, downloads, shortcode
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/form-gated-download/

## Code

```php
add_action( 'template_redirect', function () {
    // Download link from the email.
    if ( isset( $_GET['wpide_dl'], $_GET['f'], $_GET['e'] ) ) {
        $file    = absint( $_GET['f'] );
        $expires = absint( $_GET['e'] );
        $sig     = sanitize_text_field( wp_unslash( $_GET['wpide_dl'] ) );

        if ( $expires >= time() && hash_equals( wp_hash( 'dl|' . $file . '|' . $expires ), $sig ) && 'attachment' === get_post_type( $file ) ) {
            wp_safe_redirect( wp_get_attachment_url( $file ) );
            exit;
        }
        wp_die( 'This download link has expired. Please request a new one.', 'Link expired', array( 'response' => 410 ) );
    }

    if ( empty( $_POST['wpide_gate_nonce'] ) || empty( $_POST['wpide_gate_file'] ) ) {
        return;
    }

    $file = absint( $_POST['wpide_gate_file'] );
    $back = remove_query_arg( 'wpide_gate', wp_get_referer() ? wp_get_referer() : home_url( '/' ) );
    $email = sanitize_email( wp_unslash( isset( $_POST['wpide_gate_email'] ) ? $_POST['wpide_gate_email'] : '' ) );

    if ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['wpide_gate_nonce'] ) ), 'wpide_gate_' . $file ) || 'attachment' !== get_post_type( $file ) || ! is_email( $email ) || ! empty( $_POST['wpide_gate_hp'] ) ) {
        wp_safe_redirect( add_query_arg( 'wpide_gate', 'invalid', $back ) );
        exit;
    }

    $ip  = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
    $key = 'wpide_gate_' . md5( wp_salt() . $ip );
    if ( (int) get_transient( $key ) < 5 ) {
        $expires = time() + 2 * DAY_IN_SECONDS;
        $link    = add_query_arg( array( 'wpide_dl' => wp_hash( 'dl|' . $file . '|' . $expires ), 'f' => $file, 'e' => $expires ), home_url( '/' ) );
        $title   = wp_strip_all_tags( get_the_title( $file ) );

        wp_mail( $email, 'Your download: ' . $title, "Here is your download link (valid for 48 hours):\n\n$link\n\nEnjoy!" );
        wp_mail( get_option( 'admin_email' ), 'New download request', "$email requested \"$title\"." );
        set_transient( $key, (int) get_transient( $key ) + 1, HOUR_IN_SECONDS );
    }

    wp_safe_redirect( add_query_arg( 'wpide_gate', 'sent', $back ) );
    exit;
} );

add_shortcode( 'wpide_gated_download', function ( $atts ) {
    $atts = shortcode_atts( array( 'file' => 0, 'title' => 'Download the guide', 'button' => 'Email me the link' ), $atts, 'wpide_gated_download' );
    $file = absint( $atts['file'] );

    if ( ! $file ) {
        return current_user_can( 'edit_posts' ) ? '<p><em>Gated download: add file="ATTACHMENT_ID" to the shortcode.</em></p>' : '';
    }

    $status = isset( $_GET['wpide_gate'] ) ? sanitize_key( $_GET['wpide_gate'] ) : '';
    $html   = '<div class="wpide-form wpide-gated-download"><p><strong>' . esc_html( $atts['title'] ) . '</strong></p>';

    if ( 'sent' === $status ) {
        return $html . '<p role="status">Check your inbox, the download link is on its way.</p></div>';
    }

    $html .= 'invalid' === $status ? '<p role="alert">Please enter a valid email address.</p>' : '';
    $html .= '<form method="post" action=""><label class="screen-reader-text" for="wpide-gate-' . $file . '">Email address</label>';
    $html .= '<input type="email" id="wpide-gate-' . $file . '" name="wpide_gate_email" required autocomplete="email" placeholder="you@example.com"> ';
    $html .= '<span style="position:absolute;left:-9999px;" aria-hidden="true"><input name="wpide_gate_hp" tabindex="-1" autocomplete="off"></span>';
    $html .= '<input type="hidden" name="wpide_gate_file" value="' . esc_attr( $file ) . '">' . wp_nonce_field( 'wpide_gate_' . $file, 'wpide_gate_nonce', false, false );
    $html .= '<button type="submit">' . esc_html( $atts['button'] ) . '</button></form></div>';

    return $html;
} );
```

## Notes

Use [wpide_gated_download file="123" title="Free pricing guide"] with the media attachment ID; the file URL is never shown on the page and collected emails are sent to the admin.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Email-Gated Download Form" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
