I have a pictures website and I want to be able to add impressions to the database when a visitor scroll down the images. Each image viewed equal to 1 impression. This feature can be found in Facebook post impressions.

This is what I have come up with so far:

$(window).scroll(function(){
        index = $(".Picture-1A:eq(3)").offset().top;
        elementHeight = $(".Picture-1A").height();
        if(($(document).scrollTop() >= index) && ($(document).scrollTop() <= index + elementHeight)){
            // Do something here
        }
    });

Of course I will be using jQuery and Ajax.
The example above is my first attempt. I don't know how I can do it for each image. I know how to do it for one image using the :eq(index)
But I want it to update the database for each image viewed.

Dani AI

Generated

's Waypoints tip is a solid, pragmatic option for jQuery projects. For a lighter, more scalable approach on modern browsers, prefer the native Intersection Observer API: it notifies when an element crosses visibility thresholds (no per-frame scroll math), plays nicely with lazy loading and virtual lists, and keeps CPU usage low when many images are present.

Recommended rules and architecture:

  • Treat an "impression" as a visibility event with a small hold time (example: 50% visible for ~500–1000ms) to avoid counting quick scroll-past.
  • Deduplicate both client- and server-side: keep a session-level set (sessionStorage) to avoid duplicate sends, and enforce a uniqueness constraint server-side (image_id + session_id or image_id + user_id + day) depending on analytics needs.
  • Batch client sends (queue + periodic flush) and use navigator.sendBeacon on unload to avoid lost counts.
  • Be mindful of bots and privacy: filter obvious bot traffic, hash IPs if storing them, and choose a dedupe policy that fits reporting requirements.

Minimal client pattern (IntersectionObserver + hold timer + session dedupe + batching):

const counted = new Set(JSON.parse(sessionStorage.getItem('countedImgs')||'[]'));
const queue = [];
const sendQueue = () => { if (!queue.length) return; fetch('/api/impressions', {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(queue.splice(0))}); };

const obs = new IntersectionObserver((entries) => {
  entries.forEach(e => {
    const id = e.target.dataset.imageId; if (!id || counted.has(id)) return;
    if (e.isIntersecting && e.intersectionRatio >= 0.5) {
      e.target._timer = setTimeout(() => {
        if (e.target && e.target.getBoundingClientRect().height && !counted.has(id)) {
          counted.add(id); sessionStorage.setItem('countedImgs', JSON.stringify([...counted]));
          queue.push({image_id:id, ts:Date.now()}); if (queue.length >= 10) sendQueue();
        }
      }, 700);
    } else clearTimeout(e.target._timer);
  });
},{threshold:[0.5]});

document.querySelectorAll('.picture').forEach(el=>obs.observe(el));
window.addEventListener('beforeunload', ()=> { if (queue.length) navigator.sendBeacon('/api/impressions', JSON.stringify(queue)); });

Server-side: keep an impressions table (image_id, session_id, user_id nullable, counted_at) and a unique index matching the chosen dedupe policy. Small differences in threshold/hold-time will change counts; pick a rule that matches the product's definition of "view" and document it for analytics. For reference on the API, see the Intersection Observer docs (MDN).

I have found great plugin that works perfectly it's called, waypoint. You can search for it using Google
Here is a link to the plugin: http://imakewebthings.com/waypoints/
Just follow the guide on the website, easy and simple.
If you are having problems search through Stackoverflow using keyword: jquery waypoint

commented: thanks for sharing! +14
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.