Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Intercept External Links

5.00/5 (4 votes)
20 Feb 2020CPOL6 min read 10.4K   69  
This article will present a method whereby external links can be intercepted and processed.

1. Introduction Table of Contents

Web pages provide links to other web pages, some to web pages contained within the same website; others to web pages external to the referrer's website. I refer to the latter as external links and it is those links that I discuss in this article.

This article will present a method whereby external links can be intercepted and processed.

1.1. Development Directory Structure Table of Contents

When I coded the JavaScript for this project, I decided to incorporate the code for intercepting redirection in master_page.js from Breadcrumbs Generation Tool [ ^ ]. Software was developed in the master-page environment and then transferred to the stand-alone environment. The stand-alone version, in a separate directory structure, is provided to avoid requiring a developer to use a master-page solution. And while modifying the JavaScript, I removed some bugs that were undetected earlier.

The directory structures for both master-page and stand-alone versions of the interception of external links are:

MasterPage_Intercept_External_Link StandAlone_Intercept_External_Link
Contents  
constants.json  
footer.ini  
header.ini  
menu.ini  
menu.json  
CSS CSS
master_page.css intercept_external_link.css
Images Images
favicon.ico favicon.ico
green_dot.png  
ocean2.gif  
printer.png  
printer_hover.png  
site_logo.png  
under_construction.png  
Scripts Scripts
master_page.js intercept_external_link.js
contact_webmaster.html  
index.html index.html
link_1.html link_1.html
link_2.html link_2.html
link_3.html link_3.html
link_4.html link_4.html
master_pages_template.html redirection.html
privacy_policy.html stand_alone_template.html
redirection.html  

Both directories are included in the download.

2. Using the Code Table of Contents

Using Breadcrumbs Generation Tool [ ^ ] as a guide, I decided that the detection of external links should be controlled by the contents of a JSON parameter declared in the <head> of each page (that is to detect external links) and then passed to build_page, the event handler for the <body> element's onload event.

In this article,

  • The term "current page" refers to the HTML page that is about to be displayed, potentially containing an external link.
  • The symbols < and > (note bolded) surround user supplied information.

2.1. Master Page Interception of External Links Table of Contents

The following are the prerequisites for detecting external linkage in a master-page environment:

  • master_page.js must be included in the current page, as in:
    C#
    <script src="<scripts-directory>/master_page.js"></script>
    
  • The build_page method must be invoked as part of the form load event, as in:
    C#
    <body onload="MasterPage.build_page ( PAGE_COMPONENTS );">
    

2.2. Stand-alone Interception of External Links Table of Contents

The following are the prerequisites for detecting external linkage in a stand-alone environment:

  • intercept_external_link.js must be included in the current page, as in:
    C#
    <script src="<scripts-directory>/intercept_external_link.js"></script>
    
  • The build_page method must be invoked as part of the form load event, as in:
    C#
    <body onload="InterceptExternalLinks.build_page ( PAGE_COMPONENTS );">
    

2.3. PAGE_COMPONENTS Table of Contents

The PAGE_COMPONENTS parameter needs to be passed to the build_page method for both the master-page and the stand-alone environments. There are three recognized name/value pairs in the JSON object that control the processing:

Name Value Type
intercept_external_links Are external links to be intercepted? If false, interception of external links will not occur. Boolean
redirection_page_url URL of the redirection alert HTML page URL
debug_json Are the contents of the PAGE_COMPONENTS to be displayed? Boolean

For example:

HTML
<head>

  <title>Home</title>

  <meta http-equiv="Content-type"
        content="text/html; charset=UTF-8" />
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0" />

  <script>
    var PAGE_COMPONENTS =
          {
          "intercept_external_links":true,
          "redirection_page_url":"redirection.html",

          "debug_json":false

          }; // PAGE_COMPONENTS
  </script>

</head>

For master-pages PAGE_COMPONENTS, the intercept_external_links and redirection_page_url parameters are added.

In both environments (stand-alone and master-page), detecting external linkage will only occur if intercept_external_links is true and a redirection landing page URL is provided in redirection_page_url.

2.4. Redirection Landing Page Table of Contents

When an external link is intercepted, the redirection landing page is opened with a query string containing the href of the external link. For example, if the external link was

HTML
<a href="https://google.com">Google</a>

the redirection page would be opened by:

redirection.html?link=https%3A%2F%2Fgoogle.com

The redirection landing page for this project's stand-alone environment is:

HTML
<!DOCTYPE html>
<html lang="en">

  <head>

    <title>Redirection Alert</title>

    <meta http-equiv="Content-type" 
          content="text/html; charset=UTF-8" />
    <meta name="viewport" 
          content="width=device-width, initial-scale=1.0" />

    <link rel="icon" 
          type="image/x-icon" 
          href="Images/favicon.ico"/>

    <link rel="stylesheet" 
          href="https://www.w3schools.com/w3css/4/w3.css" /> 
    <link rel="stylesheet" 
          href="CSS/intercept_external_link.css" /> 

<!-- place additional scripts here (e.g., Google Analytics, etc.) -->

    <script type="text/javascript">
      var PAGE_COMPONENTS =
            { 

            "intercept_external_links":false,
            
            "debug_json":false 
            
            }; // PAGE_COMPONENTS

    </script>

  </head>

  <body onload="InterceptExternalLinks.build_page ( PAGE_COMPONENTS );">

    <div id="header"></div>

    <div id="contents" 
         style="margin-left:20%; 
                margin-right:20%; 
                width:50%;" >
      <h3 class="w3-text-red" 
          style="font-weight:bold;">Redirection Warning</h3>
      <p>
        You are now leaving this website. Links to external sites are 
        provided for user convenience and imply no endorsement. Note 
        that the privacy policy of the linked site may differ from 
        that of this site.
      </p>
      <p>
        Use the browser's Back button to return to the previous page.
      </p>
      <p>
        Proceed to <a id="next_site"
                      href="#"
                      target="_blank">this page</a> (in a new window)
      </p>
    </div>

    <div id="footer" 
         style="margin-top:20px; 
                padding-top: 20px;" >
    </div>

    <script type="text/javascript" 
            src="Scripts/intercept_external_link.js"></script>

    <script>
    
      // *********************************************** onload script

      var link_query_string_parameter = 
            InterceptExternalLinks.   
                get_query_string_parameter ( 'link' );
      
      link_query_string_parameter = 
        link_query_string_parameter.trim ( );
        
      if ( link_query_string_parameter.length > 0 )
        {
        var a = document.getElementById ( 'next_site' );
        
        a.href = link_query_string_parameter;
        a.innerHTML = link_query_string_parameter;
        }
        
    </script>
  
  </body>

</html>

For this project's stand-alone redirection landing page, the page would display as

Redirection Alert

3. Implementation Table of Contents

The implementation of the detection of external links is contained in the intercept_external_link.js and the master_page.js JavaScript files. The logic is the same. For this discussion, I will refer to the intercept_external_link.js.

3.1. onload Event Handler Registration Table of Contents

The most efficient way in which to detect a redirection to an external link is to add a click event handler to the about-to-be-displayed page.

C#
:
                                    // add a click event handler
                                    // at the document level only
                                    // if the user wants to
                                    // intercept external links
if ( !components.intercept_external_links )
  {
  return;
  }
                                    // and then only if the user
                                    // has provided a redirection
                                    // landing page
if ( !components.redirection_page_url )
  {
  return;
  }
                                    // and the redirection landing
                                    // page exists
var redirection_page_url_contents =
      read_contents ( components.redirection_page_url );

if ( !redirection_page_url_contents )
  {
  return;
  }
                                    // save the url of the
                                    // redirection landing page
                                    // for the click handler
redirection_page = components.redirection_page_url;
                                    // attach the event handler to
                                    // the document
if ( document.addEventListener )
  {
  document.addEventListener ( 'click',
                              intercept_click_event );
  }
else if ( document.attachEvent )
  {
  document.attachEvent ( 'onclick',
                         intercept_click_event );
  }

The intercept_click_event method is now registered as the handler for any click that occurs on the page.

3.2. intercept_click_event Event Handler Table of Contents

Because intercept_click_event will be triggered on every click that occurs on the page, it must react quickly when invoked. A test is made to insure that the tag name of the tag upon which a click occurred is an anchor (<a>) tag. If the test fails, the handler returns immediately.

C#
:
var href;
var target;
:
  target = e.target || e.srcElement;
                                    // insure that we only handle
                                    // anchor tags
  if ( target.tagName.toLowerCase ( ) === 'a' )
    {
    href = target.getAttribute ( 'href' );
    }
                                    // even anchor tags embedded
                                    // in an anchor tag
  else if ( e.rangeParent.tagName.toLowerCase ( ) === 'a' )
    {
    href = e.rangeParent.href;
    }
  else
    {
    return;
    }

Once that the anchor tag has been confirmed, the href of that tag is retrieved. So that we do not misinterpret pseudo protocols with external links, the following tests are performed.

C#
:
var pieces;
:
pieces = href.toString ( ).split ( ":" );
                                  // if separator does not occur
                                  // in the string, the returned
                                  // array contains one element
                                  // consisting of the entire
                                  // string
if ( pieces.length > 1 )
  {
                                  // insure that the javascript:
                                  // pseudo protocol is not the
                                  // link
  if ( pieces [ 0 ] == "javascript" )
    {
    return;
    }
  }

If the current page does not share an origin with the href, the link is an external link. It is in this code that same origin [ ^ ] is determined and enforced. Basically if the two pages do not share the same domain then the href is an external link.

C#
:
if ( retrieved_origin ( document.URL ) ===
     retrieved_origin ( href ) )
  {
  return;
  }
:

The retrieved_origin helper method is:

C#
// ********************************************** retrieved_origin

// local entry point

function retrieved_origin ( url )
  {
  var origin = parse_URL( url ).protocol.toString ( ) +
               "//" +
               parse_URL( url ).host.toString ( );

  return ( origin );

  } // retrieved_origin

and the parse_URL helper method is:

C#
// ***************************************************** parse_URL

// local entry point

// https://www.abeautifulsite.net/parsing-urls-in-javascript

function parse_URL ( url )
  {
  var parser = document.createElement ( 'a' );
  var query_items = { };
  var query_string;
                                    // let the browser do the work
  parser.href = url;
                                    // convert query string to
                                    // object
  query_string = parser.search.
                        replace ( /^\?/, '' ).
                        split ( '&' );
  for ( var i = 0; ( i < query_string.length ); i++ )
    {
    var split = query_string [ i ].split ( '=' );

    query_items [ split [ 0 ] ] = split [ 1 ];
    }

  return {    protocol: parser.protocol,
                  host: parser.host,
              hostname: parser.hostname,
                  port: parser.port,
              pathname: parser.pathname,
                search: parser.search,
           query_items: query_items,
                  hash: parser.hash
           };

  } // parse_URL

At this point an external link has been detected. The query string is prepared and the redirection landing page is opened.

C#
var url = redirection_page;
var parameters =
      {
      link:href
      };
                                  // keep browser from
                                  // responding to the link
                                  // click
e.preventDefault ( );
                                  // link to the redirection
                                  // page passing the external
                                  // url with a query string
                                  // containing the hyperlink
                                  // of the originally desired
                                  // external page
window.location.href = build_url_with_query_string (
                                              url,
                                              parameters );

The build_url_with_query_string helper method is:

C#
// *********************************** build_url_with_query_string

// https://stackoverflow.com/questions/316781/
//     how-to-build-query-string-with-javascript

function build_url_with_query_string ( url,
                                       query_string_parameters )
  {
  var query_string = "";

  for ( var key in query_string_parameters )
    {
    var value = query_string_parameters [ key ];

    query_string += encodeURIComponent ( key ) +
                    "=" +
                    encodeURIComponent ( value ) +
                    "&";
    }
  if ( query_string.length > 0 )
    {
                                      // chop off last "&"
    query_string = query_string.substring (
                                  0,
                                  ( query_string.length - 1 ) );
    url = url + "?" + query_string;
    }

  return ( url );

  } // build_url_with_query_string

4. References Table of Contents

5. Downloads Table of Contents

The download contains the two development directories. In the appropriate Scripts/ directory are found master_page.js and intercept_external_link.js.

The master_page.js file is found in the Scripts/ subdirectory of the MasterPage_Intercept_Redirection/ directory; the intercept_external_link.js file is found in the Scripts/ subdirectory of the StandAlone_Intercept_Redirection/ directory.

6. Practice and Experience Table of Contents

Master-pages detection of external links was developed first. After its development was completed, the stand-alone version was implemented by incorporating master_page.js into a new intercept_external_link.js (simply a matter of copying Javascript).

7. Conclusion Table of Contents

I have presented a method that provides developers with the ability to intercept and process external links.

8. Development Environment Table of Contents

The Intercept External Linking Tool was developed in the following environment:

Microsoft Windows 7 Professional SP 1
Microsoft Visual Studio 2008 Professional SP1
Microsoft Visual C# 2008
Microsoft .Net Framework Version 3.5 SP1

9. History Table of Contents

02/20/2020 Original article

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)