在不降低网站速度的情况下捕捉产品印象

Capturing product impression without making the website slow

我在一个拥有数千种产品的网站上工作。我必须捕捉用户在视口中可以看到的所有产品的印象。所以我创建了一个 directory 并使用了 IntersectionObserver,并在该产品的 HTML 代码中引用了它。问题在于,一旦用户滚动,它就会对移动网站产生影响。如何在不减慢我的网站速度的情况下获得印象?

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);
        }
      });
  }
}

Google Analytics 具有强大的滚动触发器以及许多其他工具。您应该将跟踪委托给有经验的一方。 GA更标准,对客户更有价值,你会更了解用户。

如果您讨厌 Google 并且必须从头开始发明自己的工具,那就去吧,不要。滚动和光标每秒触发数千个事件,并且它们冒泡到多个元素。将 GA 用于您的点击次数和热图!

只需在 createObserver() 中添加超时。像这样。

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);
    }