# fab-analytics: same-day PHP+JS GA drop-in that writes JSON to disk

Source: https://www.michaelchurley.com/blog/fab-analytics-same-day-php-js-ga-drop-in-json-disk  
Published: 2024-07-10  
Author: Michael C. Hurley  
Tags: fab-analytics, first-party-analytics, google-analytics-drop-in, php, javascript, json-logs, elementor, hustlelaunch, form-abandonment, martech, michaelmonetized, hurleyus

## Who

I still get Elementor client sites where the ask is a drop-in that records who called, who emailed, and whether the form died halfway, without paying Google for a dashboard I will not open.

For operators who will accept JSON files on a PHP host as the source of truth.

## What

I shipped **fab-analytics**, public https://github.com/michaelmonetized/fab-analytics. HEAD `8218088`. **31** commits. Version **0.1.3-rc**.

![Client pipeline](/blog/fab-analytics-same-day-php-js-ga-drop-in-json-disk/client-pipeline.png)

`fab-analytics.js` (273 LOC) builds a visit object (domain, session token, viewport, UA, referrer, language, timezone, screen), hits ipify for IP, POSTs to a hardcoded `hustlelaunch.com/.../api/post/visit/` endpoint. Tracks pageview start/exit, `mailto:` / `tel:` clicks as conversions, form submit as conversion, and a noisy set of abandonment and presave events. Session lives in localStorage (+20 minutes) plus a cookie.

![PHP JSON ingest](/blog/fab-analytics-same-day-php-js-ga-drop-in-json-disk/php-json-ingest.png)

PHP `api/post/visit/index.php` validates `domain` + `session_token`, writes `logs/{domain}/{token}-{microtime}.json`, and if the domain contains `oxstu` and the category is form, includes a `mail()` lead path to sales@hustlelaunch.com.

![Test harness](/blog/fab-analytics-same-day-php-js-ga-drop-in-json-disk/test-harness.png)

`test.html` is a Tailwind CDN harness with tel, mailto, and a required name/phone/email form. Script tag still points at `/fab.js?v=0.1.3-b-36` while the tracked file is `fab-analytics.js`.

![Gaps honesty](/blog/fab-analytics-same-day-php-js-ga-drop-in-json-disk/gaps-honesty.png)

Honest gaps: README/CHANGELOG/LICENCE.md are empty (GPL only in headers). Header @todo claims restore form fields from localStorage on return; **no restore loop in the JS**. `JSON.stringify(new FormData(form))` is not a revive path. Abandonment listeners include blur/focus/mouseleave/touchmove. Endpoint echoes file path + payload (debug leftovers). CORS `*`.

Sibling surface to keep straight: BestWNC's 2026 null-honesty directory analytics is a different product. This repo is the PHP+JS GA drop-in that writes JSON under hustlelaunch.com.

## Where

Code: [github.com/michaelmonetized/fab-analytics](https://github.com/michaelmonetized/fab-analytics), public.

```bash
git clone https://github.com/michaelmonetized/fab-analytics.git
# drop fab-analytics.js on the page; PHP tree expects logs/ writable beside api/
# client endpoint constant points at hustlelaunch.com; change before self-host
```

## When

**2024-07-09 07:14 ET.** Empty init. Midday: base JS + endpoints + test. Evening: Tailwind thrash, trailing-slash facepalm, cache-busting, PHP error handling. **22:30 ET:** `tests passed - first production run`. **2024-07-10 09:07 ET:** cleanup, HEAD `8218088`. Queue `pushed_at` **2026-01-31T10:35:32Z** (no newer commits).

![Commit arc](/blog/fab-analytics-same-day-php-js-ga-drop-in-json-disk/commit-arc.png)

## Why

A first-party GA drop-in only earns its keep if conversions and abandonments land somewhere you own, even when that somewhere is a folder of JSON files.

**Engagement Q:** Fix the empty docs, fab.js rename, and FormData revive path first, or rip the abandonment spam down to submit plus intentional blur only?
