भरोसा अच्छा है और निगरानी करना बेहतर है: इंटरसेक्शन ऑब्ज़र्वर v2

इंटरसेक्शन ऑब्ज़र्वर v2 की मदद से, न सिर्फ़ हर सेक्शन के प्रतिच्छेदन को देखा जा सकता है, बल्कि यह भी पता लगाया जा सकता है कि चौराहे के समय एक-दूसरे को काटने वाला एलिमेंट दिख रहा था या नहीं.

इंटरसेक्शन ऑब्ज़र्वर v1 उन एपीआई में से एक है जिन्हें शायद सभी लोग पसंद करते हैं और अब जब Safari यह भी काम करता है, इसलिए इसे सभी मुख्य ब्राउज़र में इस्तेमाल किया जा सकता है. एपीआई को जल्दी से समझने के लिए, हमारी सलाह है कि आप Intersection ऑब्ज़र्वर v1 पर Surma का सुपरचार्ज्ड माइक्रोटिप देखें, जिसे नीचे एम्बेड किया गया है. आप चाहें, तो सूरमा का ज़्यादा जानकारी वाला लेख भी पढ़ सकते हैं. लोगों ने कई तरह के इस्तेमाल के लिए 'इंटरसेक्शन ऑब्ज़र्वर' v1 का इस्तेमाल किया है. जैसे, इमेज और वीडियो को लेज़ी लोड करना, एलिमेंट के position: sticky पर पहुंचने पर, आंकड़ों के इवेंट को फ़ायर करना वगैरह.

पूरी जानकारी के लिए, MDN पर इंटरसेक्शन ऑब्ज़र्वर दस्तावेज़ देखें. हालांकि, छोटे रिमाइंडर के तौर पर, ज़्यादातर बुनियादी मामलों में Intersection निगरानी v1 एपीआई ऐसा ही दिखता है:

const onIntersection = (entries) => {
  for (const entry of entries) {
    if (entry.isIntersecting) {
      console.log(entry);
    }
  }
};

const observer = new IntersectionObserver(onIntersection);
observer.observe(document.querySelector('#some-target'));

इंटरसेक्शन ऑब्ज़र्वर v1 में क्या मुश्किल आ रहा है?

साफ़ तौर पर बता दें, इंटरसेक्शन ऑब्ज़र्वर v1 बहुत अच्छा है, लेकिन यह एकदम सही नहीं है. कुछ कोने वाले मामले ऐसे भी होते हैं जिनमें एपीआई की परफ़ॉर्मेंस कम हो जाती है. चलिए, इस पर एक नज़र डालते हैं! इंटरसेक्शन ऑब्ज़र्वर v1 एपीआई आपको यह बता सकता है कि किसी एलिमेंट को विंडो के व्यूपोर्ट में कब स्क्रोल किया जाता है, लेकिन यह आपको यह नहीं बताता कि एलिमेंट को किसी दूसरे पेज कॉन्टेंट (यानी, एलिमेंट को शामिल किया गया) से कवर किया गया है या नहीं. इसके अलावा, यह भी बताया जा सकता है कि एलिमेंट के विज़ुअल डिसप्ले में transform, opacity, filter वगैरह जैसे विज़ुअल इफ़ेक्ट की मदद से बदलाव किया गया है या नहीं. ऐसा करने से, यह असरदार बन सकता है.

टॉप लेवल दस्तावेज़ में मौजूद किसी एलिमेंट के लिए, JavaScript की मदद से DOM का विश्लेषण करके इस जानकारी को तय किया जा सकता है. उदाहरण के लिए, DocumentOrShadowRoot.elementFromPoint() के ज़रिए और फिर ज़्यादा जानकारी हासिल करके. इसके उलट, अगर जिस एलिमेंट की शिकायत की गई है वह तीसरे पक्ष के iframe में मौजूद है, तो वही जानकारी नहीं मिल सकती.

असल में प्रॉडक्ट दिखने के मामले में इतना ज़्यादा क्यों है?

दुर्भाग्य से, इंटरनेट एक ऐसी जगह है जो बुरे इरादों वाले लोगों को आकर्षित करती है. उदाहरण के लिए, किसी कॉन्टेंट साइट पर हर क्लिक का पेमेंट (पीपीसी) विज्ञापन दिखाने वाले किसी शेड पब्लिशर को न बढ़ाने के लिए बढ़ावा दिया जा सकता है. इससे पब्लिशर का विज्ञापन पेआउट बढ़ाने के लिए, लोगों से अपने विज्ञापनों पर क्लिक कराने के लिए कहा जा सकता है. ऐसा कम से कम कुछ समय के लिए, जब तक विज्ञापन नेटवर्क कंपनी उन्हें पकड़ न ले. आम तौर पर, ऐसे विज्ञापन iframes में दिखाए जाते हैं. अब अगर पब्लिशर चाहता कि उपयोगकर्ता ऐसे विज्ञापनों पर क्लिक करे, तो वह सीएसएस नियम iframe { opacity: 0; } लागू करके और iframe को किसी आकर्षक चीज़ के ऊपर ओवरले करके, विज्ञापन iframe को पूरी तरह से पारदर्शी बना सकता है. जैसे, बिल्लियों का एक प्यारा वीडियो, जिस पर उपयोगकर्ता वाकई क्लिक करना चाहेंगे. इसे क्लिकजैकिंग कहा जाता है. आप इस डेमो के ऊपरी हिस्से में इस तरह के क्लिकजैकिंग हमले को देख सकते हैं (बिल्ली का वीडियो "देखने" की कोशिश करें और "ट्रिक मोड" चालू करें). आप देखेंगे कि iframe में मौजूद विज्ञापन "सोचता है" कि उसे वैध क्लिक मिले थे, भले ही उस समय आपने (अचानक रूप से) क्लिक करते समय पूरी तरह पारदर्शी था.

किसी विज्ञापन पर क्लिक करने के लिए, उपयोगकर्ता को धोखा देना. इसके लिए, विज्ञापन की स्टाइल को पारदर्शी बनाएं और उसे किसी आकर्षक चीज़ पर ओवरले कर दें.

'इंटरसेक्शन ऑब्ज़र्वर वर्शन 2' इसे कैसे ठीक करता है?

इंटरसेक्शन ऑब्ज़र्वर v2 में, टारगेट किए गए एलिमेंट की असल "किसको दिखे" को ट्रैक करने का सिद्धांत दिया गया है. यह ऐसा सिद्धांत है जिसे कोई इंसान तय करेगा. IntersectionObserver कंस्ट्रक्टर में कोई विकल्प सेट करने पर, IntersectionObserverEntry इंस्टेंस को इंटरसेक्ट करने पर, isVisible नाम का एक नया बूलियन फ़ील्ड शामिल हो जाएगा. isVisible के लिए true वैल्यू, लागू किए जाने से इस बात की मज़बूत गारंटी होती है कि टारगेट एलिमेंट में कोई और कॉन्टेंट नहीं है. साथ ही, इसमें ऐसा कोई विज़ुअल इफ़ेक्ट नहीं है जो स्क्रीन पर दिखने वाले डिसप्ले के डिसप्ले को बदल दे या डिस्टॉर्ट कर दे. वहीं, false वैल्यू का मतलब है कि लागू करने से वह गारंटी नहीं मिल सकती.

spec की एक अहम जानकारी यह है कि लागू करने की अनुमति है, ताकि गलत नेगेटिव को रिपोर्ट किया जा सके. इसका मतलब है कि isVisible को false पर सेट करना, भले ही टारगेट एलिमेंट पूरी तरह से दिख रहा हो और उसमें कोई बदलाव न किया गया हो. परफ़ॉर्मेंस या दूसरी वजहों से, ब्राउज़र खुद को बाउंडिंग बॉक्स और आयताकार ज्यामिति की मदद से सीमित तौर पर काम करते हैं. वे border-radius जैसे बदलावों के लिए, बेहतरीन पिक्सल के साथ काम करने की कोशिश नहीं करते.

इसका मतलब है कि किसी भी स्थिति में फ़ॉल्स पॉज़िटिव की अनुमति नहीं है. इसका मतलब है कि जब टारगेट एलिमेंट पूरी तरह से न दिखे और न ही उसमें बदलाव किया गया हो, तो isVisible को true पर सेट करें.

नया कोड कैसा दिखता है?

अब IntersectionObserver कंस्ट्रक्टर, दो अतिरिक्त कॉन्फ़िगरेशन प्रॉपर्टी इस्तेमाल करता है: delay और trackVisibility. delay वह संख्या है जो किसी दिए गए टारगेट के लिए, ऑब्ज़र्वर से सूचनाओं के बीच कम से कम मिलीसेकंड में देरी को दिखाती है. trackVisibility एक बूलियन है जो बताता है कि ऑब्ज़र्वर, टारगेट के दिखने में हुए बदलावों को ट्रैक करेगा या नहीं.

इस बात पर ध्यान देना ज़रूरी है कि जब trackVisibility, true हो, तो delay कम से कम 100 होना चाहिए. इसका मतलब है कि हर 100 मि॰से॰ में एक सूचना से ज़्यादा नहीं होना चाहिए. जैसा कि पहले बताया गया है, विज़िबिलिटी का हिसाब लगाना महंगा है. यह शर्त, फ़ोन की परफ़ॉर्मेंस में होने वाली गिरावट और बैटरी की खपत को रोकने के लिए एक सावधानी है. ज़िम्मेदार डेवलपर, देरी के लिए सबसे बड़ी वैल्यू का इस्तेमाल करेगा.

मौजूदा spec के मुताबिक, 'किसको दिखे' सेटिंग का हिसाब इस तरह से लगाया जाता है:

  • अगर ऑब्ज़र्वर का trackVisibility एट्रिब्यूट false है, तो टारगेट को 'दिखने वाला' माना जाता है. यह मौजूदा v1 व्यवहार के मुताबिक है.

  • अगर टारगेट में 2D ट्रांसलेशन या आनुपातिक 2D अपस्केलिंग के अलावा, कोई असरदार ट्रांसफ़ॉर्मेशन मैट्रिक्स है, तो टारगेट को न दिखने वाला माना जाता है.

  • अगर टारगेट या उसमें शामिल ब्लॉक चेन के किसी एलिमेंट की ओपैसिटी, 1.0 के अलावा किसी और की है, तो टारगेट को दिखाई न देने वाला मान लिया जाता है.

  • अगर टारगेट या उसमें शामिल ब्लॉक चेन के किसी भी एलिमेंट में कोई फ़िल्टर लागू किया गया है, तो टारगेट को न दिखने वाला माना जाता है.

  • अगर लागू करने से इस बात की गारंटी नहीं मिलती कि टारगेट पर किसी दूसरे पेज का कॉन्टेंट नहीं है, तो टारगेट को 'न दिखने वाला कॉन्टेंट' माना जाता है.

इसका मतलब है कि मौजूदा तरीके से लागू होने की प्रोसेस बहुत पुरानी है. साथ ही, यह भी पक्का होता है कि लागू की गई प्रोसेस, प्रॉडक्ट के दिखने की गारंटी दी गई हो. उदाहरण के लिए, filter: grayscale(0.01%) जैसे किसी ग्रेस्केल फ़िल्टर को लागू करने या opacity: 0.99 के साथ ऐसी पारदर्शिता सेट करने से जो करीब-करीब नहीं दिखती है वह एलिमेंट ग्लोब पर नहीं दिखेगा.

यहां एपीआई की नई सुविधाओं के बारे में बताने वाला छोटा कोड सैंपल दिया गया है. डेमो के दूसरे सेक्शन में इसका क्लिक ट्रैकिंग तर्क देखा जा सकता है (लेकिन अब, पिल्ले का वीडियो "देखने" की कोशिश करें). खुद को तुरंत एक शेड पब्लिशर में बदलने के लिए, "ट्रिक मोड" को फिर से चालू करें. साथ ही, देखें कि Intersection सलाह देने वाला वर्शन 2, गैर-कानूनी विज्ञापन पर होने वाले क्लिक को ट्रैक होने से कैसे रोकता है. इस बार, इंटरसेक्शन ऑब्ज़र्वर v2 ने हमारा साथ दिया है! 🎉

इंटरसेक्शन ऑब्ज़र्वर v2, किसी विज्ञापन पर अनचाहे क्लिक को रोकता है.

<!DOCTYPE html>
<!-- This is the ad running in the iframe -->
<button id="callToActionButton">Buy now!</button>
// This is code running in the iframe.

// The iframe must be visible for at least 800ms prior to an input event
// for the input event to be considered valid.
const minimumVisibleDuration = 800;

// Keep track of when the button transitioned to a visible state.
let visibleSince = 0;

const button = document.querySelector('#callToActionButton');
button.addEventListener('click', (event) => {
  if ((visibleSince > 0) &&
      (performance.now() - visibleSince >= minimumVisibleDuration)) {
    trackAdClick();
  } else {
    rejectAdClick();
  }
});

const observer = new IntersectionObserver((changes) => {
  for (const change of changes) {
    // ⚠️ Feature detection
    if (typeof change.isVisible === 'undefined') {
      // The browser doesn't support Intersection Observer v2, falling back to v1 behavior.
      change.isVisible = true;
    }
    if (change.isIntersecting && change.isVisible) {
      visibleSince = change.time;
    } else {
      visibleSince = 0;
    }
  }
}, {
  threshold: [1.0],
  // 🆕 Track the actual visibility of the element
  trackVisibility: true,
  // 🆕 Set a minimum delay between notifications
  delay: 100
}));

// Require that the entire iframe be visible.
observer.observe(document.querySelector('#ad'));

स्वीकार हैं

इस लेख को पढ़ने के लिए, साइमन विंसेंट, योव वाइस, और Mathias Bynens को धन्यवाद. इसके अलावा, Chrome में इस सुविधा को लागू करने और इसकी समीक्षा करने के लिए, Stefan Zager को भी धन्यवाद. Unsplash पर सर्गेई सेमिन की हीरो इमेज.