Detecting In App WebViews in GTM: Filtering Android/iOS WebViews from Browser List

We are trying to accurately detect whether a user is viewing our customers site through an in-app WebView (like Android WebView or Safari in-app) versus a normal browser. The goal is to filter in-app WebViews from GA4 browser reports using Google Tag Manager.

We originally wrote a Custom JavaScript variable in GTM to detect the browser:

function() {
  var ua = navigator.userAgent;

  if (ua.indexOf("Chrome") > -1 && ua.indexOf("Edge") === -1 && ua.indexOf("OPR") === -1) {
    return "Chrome";
  } else if (ua.indexOf("Firefox") > -1) {
    return "Firefox";
  } else if (ua.indexOf("Safari") > -1 && ua.indexOf("Chrome") === -1) {
    return "Safari";
  } else if (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident/") > -1) {
    return "IE";
  } else if (ua.indexOf("Edge") > -1) {
    return "Edge";
  } else if (ua.indexOf("OPR") > -1) {
    return "Opera";
  } else if (ua.indexOf("wv") > -1) {
    return "Android Webview";
  } else {
    return "Other";
  }
}

A suggested improvement added detection for iOS WebViews and some common in-app browsers:

function() {
  var ua = navigator.userAgent || "";

  // Detect common in-app environments
  if (/bFBAN|FBAV|Instagram|Line|Twitter|LinkedInApp|TikTok/i.test(ua)) {
    return "In-App Browser";
  }

  // Android WebView
  if (ua.indexOf("wv") > -1 || (ua.indexOf("Android") > -1 && ua.indexOf("Version/") > -1 && ua.indexOf("Chrome") === -1)) {
    return "Android WebView";
  }

  // iOS WebView
  if (/iPhone|iPod|iPad/i.test(ua) && !/Safari/i.test(ua)) {
    return "iOS WebView";
  }

  // Regular browsers
  if (ua.indexOf("Chrome") > -1 && ua.indexOf("Edge") === -1 && ua.indexOf("OPR") === -1) {
    return "Chrome";
  } else if (ua.indexOf("Firefox") > -1) {
    return "Firefox";
  } else if (ua.indexOf("Safari") > -1 && ua.indexOf("Chrome") === -1) {
    return "Safari";
  } else if (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident/") > -1) {
    return "IE";
  } else if (ua.indexOf("Edge") > -1) {
    return "Edge";
  } else if (ua.indexOf("OPR") > -1) {
    return "Opera";
  } else {
    return "Other";
  }
}

We want to detect in-app WebViews reliably (Android/iOS and common social apps) and Use this detection in GTM triggers to filter out in-app WebViews from GA4 browser reports.

Example of the intended GTM trigger configuration:

Example of current GA4 Browser report showing Android/iOS WebViews:

We plan to implement a Custom JavaScript variable to detect these WebViews and then configure triggers like:

{{JS - Browser Type}} does not match RegEx (ignore case) Android Webview.*Safari.*

Our question are,

Will either of codes work as intended?
If not is there a better way to reliably detect in-app WebViews in GTM?

Synthetic event becomes stale after async operation

I’m experiencing an issue with a TextField where e.target.value
becomes stale after an async operation(FileReader API) in the onChange handler.

When I capture e.target.value in a variable before the async operation and
use that variable to update state, everything works fine. However, if I try to
access e.target.value after the async operation completes, it always contains
the old value instead of the current input value.

Why does e.target.value lose its current value after an async operation, and
why does storing it in a variable beforehand solve the problem?

React version 19.0.0

import React from 'react';
import TextField from '@mui/material/TextField';

export default function BasicCard() {

  const [a, setA] = React.useState("place");
  
  return <TextField 
        value={a} 
        onChange={async (e) => {
          const value = e.target.value; // Storing in variable - WORKS
          await new Promise((resolve) => { resolve(true) }); // FileReader API
          
          console.log(2, e.target.value); // This logs the OLD value, not current
          
          // setA(e.target.value); // This DOESN'T work - uses stale value
          setA(value); // This WORKS - uses captured value
        }}
      />
}

Expected: e.target.value should contain the current input value even after
the async operation.

Actual: e.target.value reverts to the previous value after the async operation
completes, causing the state update to fail.

Workaround: Capturing e.target.value in a const before the async operation works
correctly.

React synthetic event becomes stale after async operation

I’m experiencing an issue with a TextField where e.target.value
becomes stale after an async operation(FileReader API) in the onChange handler.

When I capture e.target.value in a variable before the async operation and
use that variable to update state, everything works fine. However, if I try to
access e.target.value after the async operation completes, it always contains
the old value instead of the current input value.

Why does e.target.value lose its current value after an async operation, and
why does storing it in a variable beforehand solve the problem?

React version 19.0.0

import React from 'react';
import TextField from '@mui/material/TextField';

export default function BasicCard() {

  const [a, setA] = React.useState("place");
  
  return <TextField 
        value={a} 
        onChange={async (e) => {
          const value = e.target.value; // Storing in variable - WORKS
          await new Promise((resolve) => { resolve(true) }); // FileReader API
          
          console.log(2, e.target.value); // This logs the OLD value, not current
          
          // setA(e.target.value); // This DOESN'T work - uses stale value
          setA(value); // This WORKS - uses captured value
        }}
      />
}

Expected: e.target.value should contain the current input value even after
the async operation.

Actual: e.target.value reverts to the previous value after the async operation
completes, causing the state update to fail.

Workaround: Capturing e.target.value in a const before the async operation works
correctly.

When I click on button the Javascript data result out HTML Source Code [duplicate]

I have tried but not work.
When I click on button then result out as a html source code.

Text

I want to view all html as a design.
Text

MY CODES

<form class="example">

    <input type="text" id="myInput" placeholder="Enter https url">
    <button id="myButton">Extract</button>
    </form>

    <div id="loadingSpinner" class="spinner"></div>
    <div id="result"></div>

When fetch result from fetch.php then It will result out data as html source code. Here I want to view all html as a style.

<script>
document.addEventListener('DOMContentLoaded', () => {
    const myInput = document.getElementById('myInput');
    const myButton = document.getElementById('myButton');
    const loadingSpinner = document.getElementById('loadingSpinner');
    const resultDiv = document.getElementById('result');

    myButton.addEventListener('click', () => {
        const inputValue = myInput.value;

        // Show loading spinner
        loadingSpinner.style.display = 'block';
        myButton.disabled = true; // Disable button during loading

        // Create a new XMLHttpRequest object
        const xhr = new XMLHttpRequest();

        // Configure the request
        xhr.open('POST', 'fetch.php', true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

        // Define what happens on successful data reception
        xhr.onload = () => {
            if (xhr.status === 200) {
                resultDiv.textContent = xhr.responseText;
            } else {
                resultDiv.textContent = 'Error: ' + xhr.status;
            }
            // Hide loading spinner and re-enable button
            loadingSpinner.style.display = 'none';
            myButton.disabled = false;
        };

        // Define what happens in case of an error
        xhr.onerror = () => {
            resultDiv.textContent = 'Network error.';
            loadingSpinner.style.display = 'none';
            myButton.disabled = false;
        };

        // Send the request with the input value
        xhr.send('data=' + encodeURIComponent(inputValue));
    });
});
</script>

Anyone Change the above code? Please edit it and send me.

How does gtag.js actually send events?

We have a react web application and we use gtag.js. I’m a backend developer and
I found some inconsistencies in our BigQuery events table. I would like to
understand how GA4 events are being sent from my browser to google’s analytics
infrastructure.

Here are some things I tried.

In the GA4 API documentation, and some articles on the web, and ChatGPT, it says
to look at the browser’s network debugger and search for POST requests to the
/collect endpoint. I do see two to three page_view events to this endpoint for
every page load (Which is also weird, why more than one? Why sometimes two,
sometimes three? Never mind for now), but we have a lot more analytics events,
for all sorts of interactions with different widgets.

I can see the events being added to dataLayer. As I use our web app, the events
keep being pushed there. But I don’t see how they leave my browser.

I installed a GA4 Debugger addon in my browser. The output of this addon seems
to be hooked in the calls to gtag(), which I already verified works, due to
changes in dataLayer. This did not give me the answer I’m seeking.

I connected our app with https://tagassistant.google.com/ and I see all the
events in there. When tagassistant is active, I can see interaction events in
the network tab leaving my browser as I interact with our app, but I guess this
is only to communicate with the tagassistant.

How does gtag.js actually send events to google? Can I observe this somehow?

Why does useEffect on [] gets called on hot reload?

app/page.tsx

"use client";

import { useEffect, useRef } from "react";
import { foo } from "./OrdersModuleFoo";
import React from "react";
const OrdersModule: React.FC = () => {
  const firstRun = useRef<boolean>();
  useEffect(() => {
    console.log("Fetching orders in OrdersModule...", firstRun.current);
    firstRun.current = true;
  }, []);
  console.log("Rendering OrdersModule");
  console.log("Foo is ", foo);
  return <div>OrdersModule Component test</div>;
};
const OrdersModuleMemo = React.memo(OrdersModule);
export default function Home() {
  return <OrdersModuleMemo />;
}

app/OrdersModuleFoo.tsx

export let foo = {
  bar: 123351354,
};
let foz = {
  bar: 15253775, // update this
};

When I update foz.bar and save the file, the next.JS app Hot Reloads. To my surprise, Fetching orders in OrdersModule... true is always printed on Hot Reload. This does not make sense to me because I thought useEffect on empty [] is called only once when components builds the first time.

Why does it do that? I am expecting that my it should not be re-rendered at all since 1) I use React.memo, 2) without props to OrdersModule 3) foz is not even exported.

Nextjs15 + agentcooper/react-pdf-highlighter , Runtime TypeError : Object.defineProperty called on non-object

Currently in My NextJs Project I am Using agentcooper/react-pdf-highlighter agentcooper/react-pdf-highlighter But Now I have to extend functionality of that.

we want to Focus on highlight from PDF it’s Needs to do 3 Clicks , we want that it’s on Single Click. because of that I imported agentcooper/react-pdf-highlighter code into My code. but now it’s Give me Error of Runtime TypeError – Object.defineProperty called on non-object

enter image description here

How To Handle This Error ?

I want to run extract react-pdf-highlighter Component and Use it into My from My code.

enter image description here

This My Folder Structure. the why i Used Their Code.

Git Repo : https://github.com/agentcooper/react-pdf-highlighter

Thank You

Securely Authenticating a React Native App with an Osclass Backend Lacking a Password Verification API Endpoint [closed]

I’m developing a React Native (Expo) app for an Osclass (PHP) backend, and I’m facing a critical authentication issue. The website’s REST API plugin has no login endpoint; it does not provide a method to verify a plain-text password against the stored Bcrypt ($2y$) hash.

I need to implement a secure login flow, but I have strict project constraints:

No Client-Side Verification: This is insecure as it would expose the hash, and it’s non-functional because it wouldn’t generate the required API token for subsequent requests.

No Server-Side Middleware: I cannot add a custom gateway (e.g., Laravel/Node.js) to handle the login logic.

No WebView: I cannot use a WebView to wrap the website’s existing login form.

Given this technical impasse, is there any established, secure pattern to authenticate a native app under these conditions? Or is the only viable solution to modify the backend PHP plugin to add the missing login functionality?

How to prevent scroll the parent website when mouse is inside a webview

I have a webview iframe inside a parent web. The webview is scrollable. My problem is when scroll to bottom of webview, if you still scroll the mouse, the parent content is also scrolled.

What I tried: when mouse enter the webview, disable the wheel event of the parent, but not work. There’s solution add class name like overflow-hidden to parent is not possible because this would make parent flicked.

I have made a demo here: https://codesandbox.io/p/sandbox/9wc4v3?file=%2Findex.html%3A7%2C33

I also tried these advice but not work:
Prevent parent page from scrolling when mouse is over embedded iframe in Firefox

const target = document.getElementById("webview");

if (target) {
  // Define event handler
  const preventScroll = (e) => e.preventDefault();

  // Track mouse position relative to the div
  target.addEventListener("mouseenter", () => {
    // Disable scroll globally
    window.addEventListener("wheel", preventScroll, { passive: false });
    window.addEventListener("touchmove", preventScroll, { passive: false });
    window.addEventListener("keydown", preventKeyScroll, { passive: false });
  });

  target.addEventListener("mouseleave", () => {
    // Re-enable scroll
    window.removeEventListener("wheel", preventScroll);
    window.removeEventListener("touchmove", preventScroll);
    window.removeEventListener("keydown", preventKeyScroll);
  });
}

function preventKeyScroll(e) {
  const keys = [32, 33, 34, 35, 36, 37, 38, 39, 40];
  if (keys.includes(e.keyCode)) {
    e.preventDefault();
  }
}

What I expecting: when mouse is inside the webview, disable the scroll of parent

How to show currently pointed series values in LightningChart JS legend

I am using LightningChart JS library (https://www.npmjs.com/package/@lightningchart/lcjs) to display several line trends with scrolling time window. The data is coming over from websocket in real-time.

In the library, there is built-in functionality that I can place my mouse over the chart and there is a popup showing the nearest values from all the trends. This is very good, but I need it to behave a bit differently. Instead of an obstructive popup, I need the values to be displayed on the side. To understand better, please see this interactive chart as a starting point for my problem:

const {
  lightningChart, Themes, LegendPosition,
  AxisScrollStrategies, AxisTickStrategies
} = lcjs

const lc = lightningChart()
const chart = lc.ChartXY({ 
    theme: Themes.light,
    defaultAxisX: {
        type: 'linear-highPrecision'
    },
    legend: {
        position: LegendPosition.TopLeft
    }
})
chart.setTitle('')
chart.axisX
    .setScrollStrategy(AxisScrollStrategies.scrolling)    
    .setTickStrategy(AxisTickStrategies.DateTime)
    .setInterval({ start: 0, end: 10000, stopAxisAfter: false })

const series1 = chart.addLineSeries({ schema: { x: { pattern: 'progressive' }, y: { pattern: null } } }).setName('Trend 1')
const series2 = chart.addLineSeries({ schema: { x: { pattern: 'progressive' }, y: { pattern: null } } }).setName('Trend 2')
const series3 = chart.addLineSeries({ schema: { x: { pattern: 'progressive' }, y: { pattern: null } } }).setName('Trend 3')

setInterval(() => {
    const x = Date.now()
    series1.appendSample({ x, y: Math.random() })
    series2.appendSample({ x, y: Math.random() * 10 })
    series3.appendSample({ x, y: -Math.random() * 5 })
}, 1000/60)
<script src="https://cdn.jsdelivr.net/npm/@lightningchart/[email protected]/dist/lcjs.iife.js"></script>

Note the legend in top left. Ideally I would want the currently pointed values to be displayed there. Currently it says “Trend 1”, “Trend 2”, etc. always. When mouse is over the chart, I’d want them to show like this “Trend 1: 10.1”

I found the cursor documentation here https://lightningchart.com/js-charts/docs/features/cursor/#custom-cursors
Most notably there is “Custom cursors” section, which does mention the availability of an API to plug in custom cursor logic. I tried adding this:

chart.setCustomCursor((event) => {
    console.log(event)
})

The result is something like this:

{
   hits: [
      cursorPosition,
      iSample,
      x,
      y,
      sample,
      ...
   ]
}

The y value is everything I need, so this is good. But I haven’t been able to find the way to connect this to the legend. I found the following potential APIs but didn’t really even know what parameters to give them:

The cursor formatting override seemed most promising but I don’t think it works together with setCustomCursor as it doesn’t seem to affect anything in the console debug.

I think the right solution is something under chart.legend.setOptions but I can’t seem to find the right syntax.

How can I load different styles for different pages in Angular 20 and when all assets are also different?

I’m currently working on an Angular v20+ project and facing an issue during the initial setup stage.

I have two different UI parts in my project:

  • Home (Landing Page and related public pages)

  • Dashboard (User/Admin section)

Both have separate asset sets — meaning their own CSS, JS, jQuery, Bootstrap, and other resource files.
The folder structure looks something like this:

/src/assets/
   /home/
      css/
      js/
      images/
   /dashboard/
      css/
      js/
      images/

However, the problem is that some CSS classes and JS function names are the same in both sets.
When I include both in the Angular app (even when kept in separate folders), they conflict with each other, causing the UI to break completely.

So far I’ve tried:

  • On-demand lazy loading of styles and scripts

  • Loading assets dynamically through Angular services

  • Using component-level script injection

  • Rendering and unmounting logic with conditional asset loading

Despite multiple approaches, I’m still unable to isolate both UI sections without conflicts.

I want to load Home and Dashboard assets independently —
so that when I switch between routes, their respective CSS/JS load and unload cleanly without interfering with each other.

Has anyone handled a similar structure — or can share a best practice or a GitHub example on how to manage multiple UI themes or layouts (with separate assets) in a single Angular v20+ project?

why await is used before using premade methods which is present in userSchema [closed]

why there is await before user.comparepassword. it is a method which i made in usermodel.

this is controller for user regestration

module.exports.loginUser = async (req, res) => {
    const { email, password } = req.body;
    const user = await userModel.findOne({ email }).select('+password');
    
    if (!user) {
        return res.status(400).json({ errors: [{ msg: 'invalid credentials' }] });
    }

    const isMatch = await user.comparePassword(password);
    if (!isMatch) {
        return res.status(400).json({ errors: [{ msg: 'invalid credentials' }] });
    }

    const token = await user.generateAuthToken();
    return res.status(200).json({ token, user });
};

i am expecting an explanation for this. because it does not call database, but it is using await.can you give detail explanation about the topic

why await is used before using premade methods which is present in userSchema

why there is await before user.comparepassword. it is a method which i made in usermodel.

this is controller for user regestration

module.exports.loginUser = async (req, res) => {
    const { email, password } = req.body;
    const user = await userModel.findOne({ email }).select('+password');
    
    if (!user) {
        return res.status(400).json({ errors: [{ msg: 'invalid credentials' }] });
    }

    const isMatch = await user.comparePassword(password);
    if (!isMatch) {
        return res.status(400).json({ errors: [{ msg: 'invalid credentials' }] });
    }

    const token = await user.generateAuthToken();
    return res.status(200).json({ token, user });
};

i am expecting an explanation for this. because it does not call database, but it is using await.can you give detail explanation about the topic

Parallax effect between sections and Scrolling issue

I am working on a landing page using react and tailwind. You have a sticky navigation where you click links then view scrolls to that particular section which connected to the link because section has that id. In between this you have two sections about and features where about has sticky top-0 class features also has sticky top-0 class to create a parallax style effect. When scroll down or up using any link in navbar it works well but when you click on about link if you are in the top of the page then page scrolls down smoothly to about section but when you are down further in other section like features and click about link again from the navbar the scroll doesn’t take you to about section, rather it gets stuck and you have to click a lot of time so that about section finally reappears, this is happening because of position sticky. I tried many way like normal html css anchoring, or programmatic way of scrolling still doesn’t work. I was wondering if someone can help me to solve this issue.

my navigation

import { cart, logo } from "@/assets/getAssets";
import { useScrollContext } from "@/contexts/ScrollContext";
import { useOutletContext } from "react-router-dom";

export default function Navbar() {
  const { hideTopNav } = useOutletContext<{ hideTopNav: boolean }>();
  const { setClickedSection } = useScrollContext();
  const menus = [
    {
      id: 1,
      title: "About",
      path: "about",
    },
    {
      id: 2,
      title: "Features",
      path: "features",
    },
    {
      id: 3,
      title: "FAQs",
      path: "faqs",
    },
    {
      id: 4,
      title: "Contact",
      path: "contact",
    },
  ];

  const handleScroll = (
    e:
      | React.MouseEvent<HTMLAnchorElement>
      | React.MouseEvent<HTMLButtonElement, MouseEvent>,
    targetId?: string
  ) => {
    e.preventDefault();

    if (!targetId || targetId === "#") {
      // Scroll to top if no id provided
      window.scrollTo({ top: 0, behavior: "smooth" });
      return;
    }

    const section = document.getElementById(targetId);
    setClickedSection(targetId);
    if (section) {
      const yOffset = -10; // adjust based on header height
      const y =
        section.getBoundingClientRect().top + window.pageYOffset + yOffset;
      window.scrollTo({ top: y, behavior: "smooth" });
    }
  };

  return (
    <div
      style={{ top: hideTopNav ? "0px" : "40px" }}
      className="fixed left-0 z-[9999] w-full py-6 backdrop-blur-md transition-all duration-300"
    >
      <nav className="max-w-[1200px] mx-auto flex justify-between items-center py-[6px]">
        <div>
          <img src={logo} alt="logo image" className="max-w-[169px] h-auto" />
        </div>

        {/* menus */}
        <ul className="px-[10px] py-[10px] flex gap-[64px] items-center">
          {menus.map((item) => (
            <li key={item.id}>
              <a
                className="font-manrope font-medium text-sm text-white leading-[19.6px] tracking-[-0.28px] no-underline"
                href={`#${item?.path}`}
                onClick={(e) => handleScroll(e, item?.path)}
              >
                {item?.title}
              </a>
            </li>
          ))}
        </ul>

       
      </nav>
    </div>
  );
}

example of about and feature section


export  function About() {
  return (
    <section
      id="about"
      className="bg-green-500 p-10 py-[229px] mb-[128px] h-screen flex justify-center items-center sticky top-0 "
    >
      About
    </section>
  );
}
export function Features() {
  return (
    <section
      id="about"
      className="bg-yellow-500 p-10 py-[229px] mb-[128px] h-screen flex justify-center items-center sticky top-0"
    >
      Features
    </section>
  );
}

I tried normal way of html and css for scrolling in sections, even used programmatic way, using ref with global context to remove the sticky class, but since react re-renders when states change so sticky doesn’t go on the very first time, then have to click again then it will work so having a context with states didn’t helped also