9

Background: I am working with the Shopify ScriptTag which allows me to add a JavaScript file on the storefront. All I have is that script file.

Current Behaviour: There is an option, "Buy It Now", which allow customers to checkout directly by skipping Add To Cart. When they click on Buy It Now, Shopify sends a fetch() POST request to checkouts.json to create the checkout.

Problem: I need to detect that this "fetch request happened" in my own JavaScript file.

self.addEventListener('fetch', event => {
    console.log("event happened");
});

I have tried Fetch Event API, but it seems to be only working in Service Worker scope.

Is there a possibility to detect this?

Like we can detect XMLHttpRequest by overriding its open method using prototypal inheritance.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
awebartisan
  • 1,424
  • 16
  • 27
  • What do you mean by _"detect"_? The code that you have control over makes the request, correct? – guest271314 Feb 22 '19 at 04:34
  • I don't have control over the behaviour on how the request is being sent. Its happening on the same page, and my script is also there. Can I detect that "request happened"? – awebartisan Feb 22 '19 at 04:35
  • Are there ` – guest271314 Feb 22 '19 at 04:36
  • Nope. No iframes so far. Its another script file from Shopify ( vendor ) itself which makes this request. – awebartisan Feb 22 '19 at 04:39
  • 1
    See [PerformanceObserver](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver/PerformanceObserver); – guest271314 Feb 22 '19 at 04:53
  • Yes. I am currently looking at your solution. – awebartisan Feb 22 '19 at 04:54
  • See stacksnippets and value printed at `console` at this [answer](https://stackoverflow.com/a/43960912/) to the question [Get actual image url after redirect](https://stackoverflow.com/questions/43960770/get-actual-image-url-after-redirect). See also [Handling similar to ?](https://stackoverflow.com/q/41497274/) – guest271314 Feb 22 '19 at 05:05

2 Answers2

16

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.initiatorType === "fetch") {
      console.log('Fetch request detected to', entry.name);
    }
  }
});

observer.observe({
  entryTypes: ["resource"]
});

fetch('https://cors-anywhere.herokuapp.com/')
  .then(res => res.text())
  .then(text => console.log(text.split('\n')[0]));

Using Performance Observer. Thanks to @guest271314.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
awebartisan
  • 1,424
  • 16
  • 27
  • 2
    This answer should be preferred to the currently accepted answer of overwriting `window.fetch`. – Dai Apr 25 '21 at 05:53
5

Yes, you can overwrite window.fetch with your own function that calls the original window.fetch after (or before) running your own code:

const nativeFetch = window.fetch;
window.fetch = function(...args) {
  console.log('detected fetch call');
  return nativeFetch.apply(window, args);
}

fetch('https://cors-anywhere.herokuapp.com/')
  .then(res => res.text())
  .then(text => console.log(text.split('\n')[0]));
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320