Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

109
Visualizações
Capturing product impression without making the website slow

I am working on a website where we have thousands of products. I have to capture the impression of all products users can see in their viewport. So I created a directory and I used IntersectionObserver, and referred to it inside the HTML code of that product. The issue is that it's causing a performing impact on the mobile site as soon as the user scrolls. How can I capture impressions without slowing my website?

export class IntersectionObserverDirective
  implements OnDestroy, OnInit, AfterViewInit {
  @Input() debounceTime = 0;
  @Input() threshold = 1;

  @Output() visible = new EventEmitter<HTMLElement>();
  isSSR: boolean = typeof window === 'undefined';

  private observer: IntersectionObserver | undefined;
  private subject$ = new Subject<{
    entry: IntersectionObserverEntry;
    observer: IntersectionObserver;
  }>();

  constructor(private element: ElementRef) {}

  ngOnInit() {
      this.createObserver();
  }

  ngAfterViewInit() {
      this.startObservingElements();
  }

  ngOnDestroy() {
      if (this.observer) {
        this.observer.disconnect();
        this.observer = undefined;
      }
  
      this.subject$.next();
      this.subject$.complete();  
  }

  private isVisible(element: HTMLElement) {
    return new Promise(resolve => {
      const observer = new IntersectionObserver(([entry]) => {
        resolve(entry.intersectionRatio === 1);
        observer.disconnect();
      });

      observer.observe(element);
    });
  }

  private createObserver() {
    const options = {
      rootMargin: '0px',
      threshold: this.threshold,
    };

    const isIntersecting = (entry: IntersectionObserverEntry) =>
      entry.isIntersecting || entry.intersectionRatio > 0;

    this.observer = new IntersectionObserver((entries, observer) => {
      entries.forEach(entry => {
        if (isIntersecting(entry)) {
          this.subject$.next({ entry, observer });
        }
      });
    }, options);
  }

  private startObservingElements() {
    if (!this.observer) {
      return;
    }

    this.observer.observe(this.element.nativeElement);

    this.subject$
      .pipe(delay(this.debounceTime), filter(Boolean))
      .subscribe(async ({ entry, observer }) => {
        const target = entry.target as HTMLElement;
        const isStillVisible = await this.isVisible(target);

        if (isStillVisible) {
          this.visible.emit(target);
          observer.unobserve(target);
        }
      });
  }
}

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

Google Analytics has robust scroll triggers, among a host of other tools. You should delegate the tracking to a party which has experience. GA is more standard, it has more value to a client, and you will learn more about users.

If you hate Google and must invent your own tool from the ground up, go ahead and don't. The scroll and cursor fire off thousands of events a second and they bubble to multiple elements. Use GA for your clicks and heatmaps!

about 4 years ago · Juan Pablo Isaza Relatório

0

Just add a timeout in createObserver(). Something like this.

private createObserver() {
        const options = {
            rootMargin: '0px',
            threshold: this.threshold,
        };
        let timeouts = {};
        const isIntersecting = (entry: IntersectionObserverEntry) =>
            entry.isIntersecting || entry.intersectionRatio > 0;
        this.observer = new IntersectionObserver((entries, observer) => {
            entries.forEach(entry => {
                if (isIntersecting(entry)) {
                    timeouts[entry.target.id] = setTimeout(() => {
                        this.subject.next({ entry, observer });
                    }, 500);
                }
                else {
                    clearTimeout(timeouts[entry.target.id])
                }
            });
        }, options);
    }
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda