1

To protect the ads, think about creating a protective layer, that is, a transparent div after there are two or three clicks by the same user and, thus, avoid more clicks by the same visitor.

$(document).ready(function() {

   $(".ads iframe").load(function() {
      $(".layer-protect").hide();
   });
});
.ads {
    position: relative;
}
.layer-protect {
    position: absolute;
}
iframe {
  position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="ads">
    <iframe src="https://es.stackoverflow.com/"></iframe>
</div>
<div class="layer-protect">
   <p>Hi! Testing...</p>
</div>

But of course this was not enough, so apart from creating a layer I would have to delete all the links that the iframe contains

let i = 0;
$("iframe *").each(function() {
    this.pos = i;
    $(this).on("click", (e) => {
        if (localStorage.getItem("link"+i) == null) {
                localStorage.setItem("link"+i, 1);
        } else {
           let clicks = localStorage.getItem("link"+i);
           if (clicks >= 3) {
               if (typeof e.target.getAttribute("href") == "string" && e.target.getAttribute("href").toLowerCase().search(location.hostname.toString().toLowerCase()) == -1) {
                  e.preventDefault();
               }
           } else {
             localStorage.removeItem("link"+i);
             clicks++;
             localStorage.setItem("link"+i, clicks);
           }
        }
    });
i++;
});

How can I set a validity time to the data stored in localStorage without the user being online or not?


My tests:

I have created a page with the following links: iframe.html

<div>
    <a href="https://example.com" target="_black">1</a>
    <a href="https://example.com" target="_black">2</a>
    <a href="https://example.com" target="_black">3</a>
    <a href="https://example.com" target="_black">4</a>
    <a href="https://example.com" target="_black">5</a>
    <a href="https://example.com" target="_black">6</a>
    <a href="https://example.com" target="_black">7</a>
    <a href="https://example.com" target="_black">8</a>
</div>

Then this page I have loaded in an iframe

<iframe src="http://example.com/iframe.html"></iframe>

As a result it doesn't work, I can give all clicks on the links without any restriction

Note: It is difficult to determine the content of an iframe since ad providers such as google adsense do not define an exact content.

If in most cases the content of the iframe cannot be eliminated, then it will be possible to count the clicks that the iframe receives, and then create a div, a protective layer that covers the entire iframe and, thus avoid more than two or three clicks, according to the rule that I determine.

  • 1
    No need for cookies, just add some valid-until key in local storage. – skobaljic Dec 27 '20 at 13:03
  • @skobaljic How would that friend key be created? –  Dec 27 '20 at 13:07
  • 1
    @skobaljic After consulting the reference on the web, it is mentioned that it is almost impossible for the stored data to be deleted since the user is required to be active on the page. this is true? it is reliable to do it that way ... –  Dec 27 '20 at 13:22
  • Use `setTimeout()` to run a function in the future that updates localstorage. – kmoser Jan 02 '21 at 05:38
  • @kmoser could you set an example please –  Jan 02 '21 at 19:26
  • @J.Mick If all you want to do is delete everything from localstorage after, say, 30 seconds: `setTimeout( function() { localStorage.clear(); }, 30000 );`. However, a determined malicious actor can still bypass all of this. – kmoser Jan 03 '21 at 00:22
  • @kmoser That is the problem, in all the similar questions they mention a problem, I still cannot find a question with a correct and safe solution. –  Jan 03 '21 at 02:08
  • @J.Mick What problem exactly? If you want to disable links, that is solvable. If you want to prevent users from stopping you from disabling links, that's not solvable. – kmoser Jan 03 '21 at 03:13
  • @kmoser I am simply looking for how to disable the links to protect the ads to avoid the malicious user by clicking too much on the ads but I do not want it to be forever, that they can click on them again within 24 or 48 hours. –  Jan 03 '21 at 04:50
  • @J.Mick If you want a working answer you'll have to provide much more information, including an example of your HTML in the form of a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). We'll also need to know whether this is for just one page or multiple pages, and how many iframes are on the page. Also, how often does the HTML structure change? In other words, we need this info to determine the best way to uniquely identify individual links over time. – kmoser Jan 03 '21 at 06:23
  • @kmoser Dear, it does not matter in how many pages it is used, if a script works, it will work for everyone and, it does not matter how many iframes exist, since we are using the: `$ ("iframe *")` function that will cover all the iframes that exist in my website, the only thing that matters to me is that the data stored in: `localStorage.setItem ("link" + i, 1);` last for a limited time of `24` or `48` hours, but that this integration is secure and that don't be inflatable, nothing more, let's not go too far from what I asked. –  Jan 03 '21 at 07:58
  • @kmoser HTML structure is not necessary to add, I just need to be able to improve my script, my jquery code that is responsible for fulfilling its work. –  Jan 03 '21 at 08:00

3 Answers3

1

You may consider using .contents() to be able to examine the items in the HTML of the iFrame element:

$("iframe").contents();

It seems you are looking for Links, so consider the following.

  $("iframe").contents().find("a").each(function(i, el) {
    $(el).on("click", (e) => {
      if (localStorage.getItem("link" + i) == null) {
        localStorage.setItem("link" + i, 1);
      } else {
        let clicks = localStorage.getItem("link" + i);
        if (clicks >= 3) {
          if (typeof e.target.getAttribute("href") == "string" && e.target.getAttribute("href").toLowerCase().search(location.hostname.toString().toLowerCase()) == -1) {
            e.preventDefault();
          }
        } else {
          localStorage.removeItem("link" + i);
          clicks++;
          localStorage.setItem("link" + i, clicks);
        }
      }
    });
  });

It's very difficult to be sure I understand what you are trying to accomplish as you have not provided a complete example. If you want to update your post and include an example of the HTML that would appear in the iframe, people would be able to help further.

See More:

Update

If we break the objective down a bit, we can see all the steps we need to take. You report you want to track when links are clicked and if they are clicked too often or within too quick a time frame, you want to prevent the click action.

Objectives

  • Use Local storage to track the links clicked, number of clicks up on a link, last time a link was clicked
  • When a link is clicked, update the count & last time it was clicked

Example

https://jsfiddle.net/Twisty/61e3m07v/35/

JavaScript

$(function() {
  function getLinkData() {
    var strLinks = localStorage.getItem("links");
    var links = [];
    if (strLinks != null) {
      links = JSON.parse(strLinks);
    }
    return links;
  }

  function saveLinkData(arr) {
    console.log("Saving Data");
    console.log(arr);
    localStorage.setItem("links", JSON.stringify(arr));
  }

  function findLink(h, arr) {
    var result = -1;
    $.each(arr, function(i, v) {
      if (h.toLowerCase() == v.link) {
        result = i;
      }
    });
    return result;
  }

  function saveLinkClick(h) {
    var links = getLinkData();
    var ind = findLink(h, links);
    var result = true;
    if (ind >= 0) {
      // Check your current link stats
      // if meet or exceed threshold, result = false
      links[ind].count++;
      links[ind].last = Date.now();
    } else {
      links.push({
        link: h,
        count: 1,
        last: Date.now()
      });
    }
    saveLinkData(links);
    return result;
  }

  $("a").click(function(e) {
    return saveLinkClick(this.href);
  });
});

As you can see, we have a number of helper functions. These help us store the following data, as an example:

[
  {
    "link": "https://example.com/index.html?adid=8",
    "count": 1,
    "last": 1609804570776
  },
  {
    "link": "https://example.com/index.html?adid=4",
    "count": 1,
    "last": 1609804574405
  },
  {
    "link": "https://example.com/index.html?adid=5",
    "count": 3,
    "last": 1609804583245
  }
]

Complex data of this nature cannot be stored in localStorage like this. In my example, we use JSON.stringify() to create a single String of data that can be stored to localStorage. It will be stored like:

[{"link":"https://example.com/index.html?adid=8","count":1,"last":1609804570776},{"link":"https://example.com/index.html?adid=4","count":1,"last":1609804574405},{"link":"https://example.com/index.html?adid=5","count":3,"last":1609804583245}]

To help us find the URL or link in our data, we have a finder function that returns the Array Index of the link or a -1 if it is not present. We can then update existing data or append new data for a new link.

It is at this point you would want to evaluate what to do if the count is too high or the time passed is too low.

Once you have everything working the way you want for Links in a stand alone page, or test, you then want to apply the same activity to the links inside an iFrame. See my original example.

Twisty
  • 30,304
  • 2
  • 26
  • 45
  • 1
    Friend, the problem is that the links or the content of the iframe is generated by Google Adsense therefore it is difficult to determine its content. In any case, if it is not possible to delete content from an iframe, then it will be possible to count the clicks that this iframe receives and after the allowed clicks create a protective layer, a transparent div that covers all that iframe and thus avoid clicks in the ads. –  Jan 04 '21 at 04:49
  • Friend, this is valid for internal system, as I indicate you cannot modify the contents of an iframe, I remind you that the iframe or the ads are generated by google adsense in an iframe, the only thing I can do is create a container for example a `div`, `
    google iframe
    `301 characters left
    –  Jan 05 '21 at 04:20
  • Consulting on the internet I found the following `https://www.techiedelight.com/protect-your-adsense-account-from-invalid-clicks/` it may be useful to find a solution. –  Jan 05 '21 at 04:21
1

Here's a working example in pure JS (no jQuery required) that stores link clicks and last-clicked-dates in localStorage. Links are given keys link1, link2, etc. So the first link has a key of link1 and the value is the number of times it has been clicked. Last-clicked dates are given keys date1, date2, etc. and values of stringified last-clicked date.

This code assumes that the <iframe> tags are always in the same order, and that the <a> tags in them are always in the same order (and go to the same places) with every reload.

For every <iframe> on the page, upon its load event firing (important, otherwise we will try to access its HTML before it has loaded!), we cycle through all the <a> tags and assign them a sequential number via setAttribute(). We use that number in our onClick() handler to identify that link so we have a unique ID for use in localStorage.

There are liberal calls to console.log() which you may want to remove if you think they will help users figure out what's going on.

var MAX_CLICKS = 3; // Can only click a link this many times before it gets disabled
var MAX_HOURS = 12; // Disabled links get re-enabled after this many hours

function getLinkClicks( id ) {
    var clicks = parseInt( localStorage.getItem( 'link' + id ) );
    if ( isNaN( clicks ) ) {
        clicks = 0;
    }

    return clicks;
}

function setLinkClicks( id, clicks ) {
    localStorage.setItem( 'link' + id, clicks );
}

function setLinkDate( id ) {
    localStorage.setItem( 'date' + id, new Date().toString() );
}

function getLinkDate( id ) {
    var s = localStorage.getItem( 'date' + id );
    return new Date( s );
}

var i = 1; // Counter used to assign link ID numbers
var iframes = document.querySelectorAll('iframe');
iframes.forEach(function(iframe){
    iframe.addEventListener('load', function() {
        var links = iframe.contentWindow.document.getElementsByTagName('a');

        // Give this link an ID and add its click handler:
        Array.from(links).forEach(function(link){
            link.setAttribute( 'n', i ); // Tag the link with an ID
            link.addEventListener('click', function(e) {
                var id = e.target.getAttribute( 'n' ); // Get the link's assigned ID
                var clicks = getLinkClicks( id );
                clicks++;

                setLinkClicks( id, clicks );
                console.log(`Setting link ${id} to ${clicks} clicks`);

                // Determine how many hours ago it was last clicked:
                var dt = getLinkDate( id );
                var diff_hours = ( new Date() - dt ) / ( 1000 * 60 * 60 )
                console.log(`Link ${id} hours since last click = ${diff_hours}`);

                if ( 
                    clicks <= MAX_CLICKS
                        ||
                    diff_hours >= MAX_HOURS
                ) {
                    // Allow the click

                    // If we are here only because enough time elapsed, reset this link's clicks to 0:
                    if ( diff_hours >= MAX_HOURS ) {
                        setLinkClicks( id, 0 );
                    }

                    setLinkDate( id );
                    console.log( `Allowing click on link ${id}` );
                } else {
                    // Too many clicks on this link, or not enough elapsed time before it is enabled again, so disallow it:
                    console.log( `Preventing click on link ${id}` );
                    e.preventDefault();
                }
            });
            i++;
        });
    });
});
kmoser
  • 8,780
  • 3
  • 24
  • 40
  • It does not work friend, I have created some example links https://jsfiddle.net/x602s4h8/ and then I have loaded it in an iframe in https://jsfiddle.net/n1k8wmou/ and I don't see that it works, I can give all the clicks I want to give. –  Jan 04 '21 at 04:45
  • Your JSFiddle link does not include my JS code. But since you only just recently made it clear that the actual ` – kmoser Jan 04 '21 at 05:05
  • https://www.techiedelight.com/protect-your-adsense-account-from-invalid-clicks/ –  Jan 04 '21 at 13:09
1

Getting into ad iframes and trying to inspect / modify them seems like an extremely complicated job that borders on the impossible.

Therefore, what I suggest is that you create your transparent protective layer that exactly matches the size of the ad and have it always over it, enabled and capturing any clicks along with their relative coordinates. You block the clicks from bubbling down to the ad. You evaluate each click and determine wheter they should go through or not and then transfer the valid ones to the ad at the same coordinates you received them on your layer.

This solution would only work if the attacker's script is emulating user interaction via taps / clicks and not targeting the ad iframe directly.

Also, you could be running the risk of the ad server detecting your transfered clicks as artificial, being script generated.

There is only so much you can really do.

GonZo
  • 58
  • 5
  • It is exactly what I intend, but since I adapt my code with those characteristics, because my code is not counting any click, could you help me with an example. –  Jan 09 '21 at 05:35