How are you loading analytics and recaptcha? Without that information it is hard to know what may be going on.
Regardless, maybe organizing the scripts by order and making them defer instead of async would make them run in order. There is also the load event on script tags, so maybe listen for that.
Also, using requestAnimationFrame for this is super aggressive. Checking every 16 ms is a lot and is going to hurt performance. A more relaxed setTimeout with 300 or so would work well and still be basically unnoticeable to users.
I’m using the official google recommendation. The analytics are part of the Google Tag Manager and I just used the information from the Quick Start Guide:
I’m using the recaptcha v3 and loading it is just adding the script to the head:
On a submit, I send a message to JS using ports, execute the recaptcha as seen in the above code and push the token back into Elm.
I have no idea why recaptcha is failing if I start the Elm app inside that function.
This happens only once, to start the app and as soon as google analytics becomes available I’m starting the Elm app. The app has nothing else to do than wait for that library to become available.
I also tried setTimeout and it too breaks the recaptcha integration.
This is what I was trying to avoid. Basically, each page when it loads makes a request to the backend that now needs to include the google_client_id. If this is not easily available as flags, I’m left with deferring the loading of the page until I get the the google_client_id through ports. This is what I will implement if I find no other solution.
What I ended up doing is have a two way communication between Elm and JS where Elm checks to see if ga is ready and when it gets ready the google_client_id is sent back to Elm and it is saved in the model.
The functionality that needed the client_id got extracted from the init and delayed until the field in the model is set.