How can I add extra parameters after a hyperlink, for tracking purposes?

For example, let's say I inserted media into a post - http://mysite/wp-content/uploads/2018/12/My_PDF_File.pdf. How can I make a function to automatically insert the user id like this http://mysite/wp-content/uploads/2018/12/My_PDF_File.pdf?user=54

There will be multiple pdf links on the same page, I'm at a bit of a loss on how to do this.

  • What are the specific conditions in which you'd like to add the user parameter and value? Just pdf uploads, uploads to a specific post, uploads by a specific user role, or any combination of these etc. – Dave Romsey Dec 14 '18 at 18:17
  • 1
    I'm looking to track all .pdf files when they are clicked. Specifically to tell how many .pdf files a specific user is clicking. I bulk add about 30.pdf files a day, these get replaced everyday with new ones on the same page every day. – Drastec Development Dec 14 '18 at 18:35
  • How are you tracking the clicks? – czerspalace Dec 14 '18 at 19:41
  • I'm tracking with Google Analytics and MonsterInsights with 'Event' of 'download' this tells me the URL of the pdf file and how many times it was clicked but doesn't tell me who it is. So that's why I want to attach the userID to the clicked URL. – Drastec Development Dec 14 '18 at 19:46

Here's a solution that I came up with that will add the user query argument and the current user's ID to PDF links, e.g.:


This code works by inspecting the post's content using the the_content filter, then parsing the content using DOMDocument. I've run into various gotchas using DOMDocument and much of this code deals with handling those edge cases. Also note that we'll bail immediately if a user is not logged in, since there's nothing to do in that case.

The real meat and potatoes comes towards the end of wpse_append_current_user_id_to_pdf_links() where links are extracted from the content, checked to ensure they are PDFs, then add_query_arg() is used to append the user query argument and value.

 * Filters post content and appends user query argument and user ID value
 * to PDF links.
 * @param string $content post content 
add_filter( 'the_content', 'wpse_append_current_user_id_to_pdf_links' );
function wpse_append_current_user_id_to_pdf_links( $content ) {
    // Bail if there is no content to work with.
    if ( ! $content ) {
        return $content;

    // Get the current user.
    $current_user = wp_get_current_user();

    // Bail if there is nobody logged in.
    if ( ! $current_user->exists() ) {
        return $content;

    // Create an instance of DOMDocument.
    $dom = new \DOMDocument();

    // Supress errors due to malformed HTML.
    // See http://stackoverflow.com/a/17559716/3059883
    $libxml_previous_state = libxml_use_internal_errors( true );

    // Populate $dom with $content, making sure to handle UTF-8, otherwise
    // problems will occur with UTF-8 characters.
    // Also, make sure that the doctype and HTML tags are not added to our HTML fragment. http://stackoverflow.com/a/22490902/3059883
    $dom->loadHTML( mb_convert_encoding( $content, 'HTML-ENTITIES', 'UTF-8' ), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );

    // Restore previous state of libxml_use_internal_errors() now that we're done.
    libxml_use_internal_errors( $libxml_previous_state );

    // Create an instance of DOMXpath.
    $xpath = new \DOMXpath( $dom );

    // Get all links.
    $links = $xpath->query( "//a" );

    // Process the links.
    foreach ( $links as $link ) {
        $link_href = $link->getAttribute( 'href' );

        // Get the extension for this link.
        $extension = pathinfo( $link_href, PATHINFO_EXTENSION );

        // Only process PDF links.
        if ( 'pdf' === strtolower( $extension ) ) {
            $link->setAttribute( 'href', add_query_arg( 'user', $current_user->ID, $link_href ) );

    // Save and return updated HTML.
    $new_content = $dom->saveHTML();
    return $new_content;
| improve this answer | |
  • 1
    Yes! Yes! Yes! Not only does this work just like I needed, the code is commented extremely well! Thank you so much, for taking the time and interest answering my question. Thank you everyone else as well. – Drastec Development Dec 20 '18 at 19:29
  • You got it, @DrastecDevelopment! I'm glad this worked for you. Just wanted to note that It would also be possible to solve the issue using JS (and a little PHP to send the user id over to JS via wp_localize_script), but I went with the PHP route since I'm a bit more comfortable with it. – Dave Romsey Dec 20 '18 at 19:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.