# Facebook, Meta events and Firebase Analytics - JavaScript bridge API

> Facebook Login, Meta App Events and Firebase Analytics under the creator’s own keys, set in the build. Analytics collects nothing until the user has consented.

- **Applies to:** AppMint
- **Source:** extracted from the app runtime and its per-method example files; this page is generated from them.
- **HTML:** https://freewebtoapk.com/docs/api/growth

### `AppMint.analytics`

```js
AppMint.analytics — one event to Firebase and Meta
```

**Example**

Logs an event to every analytics service the build connected: Firebase Analytics (your own google-services.json) and Meta App Events. Names are cleaned to each service's rules and the answer says what was sent.

**Returns:** `log(name, params)` → `{ok, providers: {firebase?, meta?}}`, each `{ok, name, dropped}` or `{ok: false, error}`. `setUserId(id)`, `setUserProperty(name, value)`, `screenView(name, class)`, `setEnabled(on)` → Promises; `providers()` → `{firebase, meta}`. **Needs:** Integrate step → **Firebase Analytics** (upload google-services.json in the Push card) and/or **Meta App Events**.

```js
if (window.AppMint && AppMint.analytics) {
  AppMint.analytics.setUserId(currentUser.id);
  AppMint.analytics.setUserProperty('plan', 'pro');
  var r = await AppMint.analytics.log('add_to_cart', { item_id: 'sku-42', value: 19.99, currency: 'USD' });
  if (!r.ok) console.warn('not logged', r.providers);   // e.g. {firebase: {ok:false, error:'no_consent'}}
}

// Your own consent screen: nothing is collected while this is off (persisted).
document.getElementById('optOut').onchange = (e) => AppMint.analytics.setEnabled(!e.target.checked);
```

**Notes:** Consent: when the app shows ads, Google's consent form decides for analytics too - nothing is collected before it has an answer, and where the GDPR applies purpose 1 must be granted; the page's `setEnabled(false)` always wins. While collection is off, calls answer `no_consent` (nothing is queued). Firebase names: letters, digits and `_`, up to 40 characters, at most 25 parameters, string values up to 100 characters; reserved names (`first_open`, `session_start`, `firebase_…`, `google_…`, `ga_…`) answer `reserved_name` / `reserved_prefix`. `params.value` (a number) becomes Meta's value-to-sum. With **Log a screen view for every page change** on, route changes log `screen_view` automatically. Errors: `not_configured`, `missing_google_app_id`, `params_not_json`, `invalid_name`.

### `AppMint.facebook`

```js
AppMint.facebook — Facebook Login and Meta App Events
```

**Example**

"Continue with Facebook" on your OWN Facebook app. Sign-in opens Facebook in a browser tab (Custom Tab): it uses the facebook.com login of that browser, NOT the Facebook app, and returns to the app when the user confirms. Also logs Meta App Events when you switched them on.

**Returns:** `login(permissions)` → a Promise that always resolves: `{ok: true, accessToken, userId, expires, grantedPermissions, declinedPermissions}` or `{ok: false, cancelled?, error}`. `getAccessToken()` → the same token object, or `null` when signed out. `logEvent(name, valueToSum, params)` → `{ok, name, dropped}` (queued and sent in batches) or `{ok: false, error}`. **Needs:** the build's Integrate step → **Facebook Login** with your Facebook App ID and Client Token (and **Meta App Events** for `logEvent`).

**Sign in, then use the token with your backend:**

```js
async function facebookSignIn() {
  if (!(window.AppMint && AppMint.facebook)) { alert('Open this page in the app'); return; }
  var r = await AppMint.facebook.login(['public_profile', 'email']);
  if (!r.ok) {
    if (r.cancelled) return;                          // the user backed out
    alert('Facebook sign-in failed: ' + (r.message || r.error));
    return;
  }
  // Firebase: firebase.auth().signInWithCredential(firebase.auth.FacebookAuthProvider.credential(r.accessToken))
  await fetch('/api/login/facebook', { method: 'POST', body: JSON.stringify({ token: r.accessToken }) });
  console.log('Signed in as', r.userId, 'until', new Date(r.expires));
}

var existing = AppMint.facebook.getAccessToken();   // null when signed out
if (existing) showSignedIn(existing.userId);

document.getElementById('logout').onclick = () => AppMint.facebook.logout();
```

**Meta App Events:**

```js
AppMint.facebook.logEvent('fb_mobile_purchase', 9.99, { fb_currency: 'USD', fb_content_id: 'sku-42' });
AppMint.facebook.logEvent('Level Complete', null, { level: 3 });
```

**Notes:** Facebook Developers → your app → Facebook Login → Settings → Valid OAuth Redirect URIs: add `https://freewebtoapk.com/fb-return/` (the wizard has a Copy button). No key hash or Android platform setup is needed. The token is checked with Facebook (it must belong to your App ID) before the promise resolves. If Android closed the app while the user was in the browser, the result is not delivered to a promise - the token is stored and `getAccessToken()` returns it when the page starts. Errors: `not_configured`, `busy` (a login is already open), `cancelled` (also when the user closes the tab), `state_mismatch`, `wrong_app`, `failed`, `no_token`, `foreign_origin` (a page that is not the app's own). App Events (sent from the app to Facebook's App Events API with your client token) start only after consent (see `AppMint.analytics`) and answer `no_consent` until then. Web sign-in through Supabase or Firebase redirects keeps working as before.

### `analyticsLogEvent`

```js
window.WebToApk.analyticsLogEvent(name: String, paramsJson: String): String
```

Firebase event; the name is cleaned to Firebase's rules. Returns {ok, name, dropped} or {ok:false, error}.

**Example**

The raw Firebase Analytics methods behind `AppMint.analytics` - prefer the wrapper. Each returns its answer as JSON text: `{ok, name, dropped}` or `{ok: false, error}`.

**Returns:** JSON text (`analyticsSetEnabled` returns nothing). **Needs:** Integrate step → Firebase Analytics, with your google-services.json uploaded in the Push Notifications card.

```js
var r = JSON.parse(WebToApk.analyticsLogEvent('share', JSON.stringify({ method: 'whatsapp', content_type: 'post' })));
if (!r.ok) console.warn(r.error);                        // 'no_consent', 'reserved_name', …
WebToApk.analyticsLogScreenView('/checkout', 'CheckoutPage');
WebToApk.analyticsSetUserId('user-123');                 // '' clears it
WebToApk.analyticsSetUserProperty('favorite_food', 'pizza');
WebToApk.analyticsSetEnabled(false);                     // stops every analytics provider
```

**Notes:** `analyticsSetEnabled` is the page's consent switch for Firebase and Meta App Events together; see `AppMint.analytics` for the consent rules.

### `analyticsLogScreenView`

```js
window.WebToApk.analyticsLogScreenView(screenName: String, screenClass: String): String
```

Firebase screen_view for [screenName] (e.g. the route path).

**Example**

Documented together with `WebToApk.analyticsLogEvent` - the example there shows this one too.

The raw Firebase Analytics methods behind `AppMint.analytics` - prefer the wrapper. Each returns its answer as JSON text: `{ok, name, dropped}` or `{ok: false, error}`.

**Returns:** JSON text (`analyticsSetEnabled` returns nothing). **Needs:** Integrate step → Firebase Analytics, with your google-services.json uploaded in the Push Notifications card.

```js
var r = JSON.parse(WebToApk.analyticsLogEvent('share', JSON.stringify({ method: 'whatsapp', content_type: 'post' })));
if (!r.ok) console.warn(r.error);                        // 'no_consent', 'reserved_name', …
WebToApk.analyticsLogScreenView('/checkout', 'CheckoutPage');
WebToApk.analyticsSetUserId('user-123');                 // '' clears it
WebToApk.analyticsSetUserProperty('favorite_food', 'pizza');
WebToApk.analyticsSetEnabled(false);                     // stops every analytics provider
```

**Notes:** `analyticsSetEnabled` is the page's consent switch for Firebase and Meta App Events together; see `AppMint.analytics` for the consent rules.

### `analyticsSetEnabled`

```js
window.WebToApk.analyticsSetEnabled(enabled: Boolean)
```

The page's own analytics switch for every provider; persisted.

**Example**

Documented together with `WebToApk.analyticsLogEvent` - the example there shows this one too.

The raw Firebase Analytics methods behind `AppMint.analytics` - prefer the wrapper. Each returns its answer as JSON text: `{ok, name, dropped}` or `{ok: false, error}`.

**Returns:** JSON text (`analyticsSetEnabled` returns nothing). **Needs:** Integrate step → Firebase Analytics, with your google-services.json uploaded in the Push Notifications card.

```js
var r = JSON.parse(WebToApk.analyticsLogEvent('share', JSON.stringify({ method: 'whatsapp', content_type: 'post' })));
if (!r.ok) console.warn(r.error);                        // 'no_consent', 'reserved_name', …
WebToApk.analyticsLogScreenView('/checkout', 'CheckoutPage');
WebToApk.analyticsSetUserId('user-123');                 // '' clears it
WebToApk.analyticsSetUserProperty('favorite_food', 'pizza');
WebToApk.analyticsSetEnabled(false);                     // stops every analytics provider
```

**Notes:** `analyticsSetEnabled` is the page's consent switch for Firebase and Meta App Events together; see `AppMint.analytics` for the consent rules.

### `analyticsSetUserId`

```js
window.WebToApk.analyticsSetUserId(userId: String): String
```

Firebase user id ("" clears it).

**Example**

Documented together with `WebToApk.analyticsLogEvent` - the example there shows this one too.

The raw Firebase Analytics methods behind `AppMint.analytics` - prefer the wrapper. Each returns its answer as JSON text: `{ok, name, dropped}` or `{ok: false, error}`.

**Returns:** JSON text (`analyticsSetEnabled` returns nothing). **Needs:** Integrate step → Firebase Analytics, with your google-services.json uploaded in the Push Notifications card.

```js
var r = JSON.parse(WebToApk.analyticsLogEvent('share', JSON.stringify({ method: 'whatsapp', content_type: 'post' })));
if (!r.ok) console.warn(r.error);                        // 'no_consent', 'reserved_name', …
WebToApk.analyticsLogScreenView('/checkout', 'CheckoutPage');
WebToApk.analyticsSetUserId('user-123');                 // '' clears it
WebToApk.analyticsSetUserProperty('favorite_food', 'pizza');
WebToApk.analyticsSetEnabled(false);                     // stops every analytics provider
```

**Notes:** `analyticsSetEnabled` is the page's consent switch for Firebase and Meta App Events together; see `AppMint.analytics` for the consent rules.

### `analyticsSetUserProperty`

```js
window.WebToApk.analyticsSetUserProperty(name: String, value: String): String
```

Firebase user property (name up to 24 characters, value up to 36; "" clears it).

**Example**

Documented together with `WebToApk.analyticsLogEvent` - the example there shows this one too.

The raw Firebase Analytics methods behind `AppMint.analytics` - prefer the wrapper. Each returns its answer as JSON text: `{ok, name, dropped}` or `{ok: false, error}`.

**Returns:** JSON text (`analyticsSetEnabled` returns nothing). **Needs:** Integrate step → Firebase Analytics, with your google-services.json uploaded in the Push Notifications card.

```js
var r = JSON.parse(WebToApk.analyticsLogEvent('share', JSON.stringify({ method: 'whatsapp', content_type: 'post' })));
if (!r.ok) console.warn(r.error);                        // 'no_consent', 'reserved_name', …
WebToApk.analyticsLogScreenView('/checkout', 'CheckoutPage');
WebToApk.analyticsSetUserId('user-123');                 // '' clears it
WebToApk.analyticsSetUserProperty('favorite_food', 'pizza');
WebToApk.analyticsSetEnabled(false);                     // stops every analytics provider
```

**Notes:** `analyticsSetEnabled` is the page's consent switch for Firebase and Meta App Events together; see `AppMint.analytics` for the consent rules.

### `facebookLogEvent`

```js
window.WebToApk.facebookLogEvent(name: String, valueToSum: String, paramsJson: String): String
```

Meta App Event; [valueToSum] a number as text or ""; [paramsJson] a flat JSON object. Returns {ok, name, dropped} or {ok:false, error}.

**Example**

Documented together with `WebToApk.facebookLogin` - the example there shows this one too.

The raw methods behind `AppMint.facebook` - prefer the promise wrapper. Built with your Facebook App ID + Client Token (Integrate step); without them every call answers `not_configured`.

**Returns:** `facebookLogin(permissionsCsv, callbackId)` resolves `window.__appmintReplies[callbackId]`; with an empty `callbackId` the answer arrives as the `appmint:facebook-login` event. `getFacebookAccessToken()` returns the token JSON or `""`. `facebookLogEvent(name, valueToSum, paramsJson)` returns `{ok, name, dropped}` as JSON text (`valueToSum` is a number as text, or `""`). **Needs:** Facebook Login switched on in the build.

```js
window.addEventListener('appmint:facebook-login', (e) => {
  if (e.detail.ok) console.log('token', e.detail.accessToken);
  else if (!e.detail.cancelled) console.warn(e.detail.error);
});
WebToApk.facebookLogin('public_profile,email', '');

var t = WebToApk.getFacebookAccessToken();          // '' when signed out
var logged = JSON.parse(WebToApk.facebookLogEvent('Subscribe', '4.99', JSON.stringify({ plan: 'monthly' })));
WebToApk.facebookLogout();
```

**Notes:** Implemented in FacebookBridge.kt without any Facebook SDK: login is Facebook's manual web flow in a browser tab, App Events go to Facebook's App Events Graph API.

### `facebookLogin`

```js
window.WebToApk.facebookLogin(permissionsCsv: String, callbackId: String)
```

Native Facebook login; [permissionsCsv] e.g. "public_profile,email". Resolves [callbackId], or fires `appmint:facebook-login` when it is blank.

**Example**

The raw methods behind `AppMint.facebook` - prefer the promise wrapper. Built with your Facebook App ID + Client Token (Integrate step); without them every call answers `not_configured`.

**Returns:** `facebookLogin(permissionsCsv, callbackId)` resolves `window.__appmintReplies[callbackId]`; with an empty `callbackId` the answer arrives as the `appmint:facebook-login` event. `getFacebookAccessToken()` returns the token JSON or `""`. `facebookLogEvent(name, valueToSum, paramsJson)` returns `{ok, name, dropped}` as JSON text (`valueToSum` is a number as text, or `""`). **Needs:** Facebook Login switched on in the build.

```js
window.addEventListener('appmint:facebook-login', (e) => {
  if (e.detail.ok) console.log('token', e.detail.accessToken);
  else if (!e.detail.cancelled) console.warn(e.detail.error);
});
WebToApk.facebookLogin('public_profile,email', '');

var t = WebToApk.getFacebookAccessToken();          // '' when signed out
var logged = JSON.parse(WebToApk.facebookLogEvent('Subscribe', '4.99', JSON.stringify({ plan: 'monthly' })));
WebToApk.facebookLogout();
```

**Notes:** Implemented in FacebookBridge.kt without any Facebook SDK: login is Facebook's manual web flow in a browser tab, App Events go to Facebook's App Events Graph API.

### `facebookLogout`

```js
window.WebToApk.facebookLogout()
```

Signs the Facebook user out of this app (clears the cached access token).

**Example**

Documented together with `WebToApk.facebookLogin` - the example there shows this one too.

The raw methods behind `AppMint.facebook` - prefer the promise wrapper. Built with your Facebook App ID + Client Token (Integrate step); without them every call answers `not_configured`.

**Returns:** `facebookLogin(permissionsCsv, callbackId)` resolves `window.__appmintReplies[callbackId]`; with an empty `callbackId` the answer arrives as the `appmint:facebook-login` event. `getFacebookAccessToken()` returns the token JSON or `""`. `facebookLogEvent(name, valueToSum, paramsJson)` returns `{ok, name, dropped}` as JSON text (`valueToSum` is a number as text, or `""`). **Needs:** Facebook Login switched on in the build.

```js
window.addEventListener('appmint:facebook-login', (e) => {
  if (e.detail.ok) console.log('token', e.detail.accessToken);
  else if (!e.detail.cancelled) console.warn(e.detail.error);
});
WebToApk.facebookLogin('public_profile,email', '');

var t = WebToApk.getFacebookAccessToken();          // '' when signed out
var logged = JSON.parse(WebToApk.facebookLogEvent('Subscribe', '4.99', JSON.stringify({ plan: 'monthly' })));
WebToApk.facebookLogout();
```

**Notes:** Implemented in FacebookBridge.kt without any Facebook SDK: login is Facebook's manual web flow in a browser tab, App Events go to Facebook's App Events Graph API.

### `getFacebookAccessToken`

```js
window.WebToApk.getFacebookAccessToken(): String
```

The current Facebook access token as JSON {accessToken, userId, expires, grantedPermissions, declinedPermissions}, or "" when signed out.

**Example**

Documented together with `WebToApk.facebookLogin` - the example there shows this one too.

The raw methods behind `AppMint.facebook` - prefer the promise wrapper. Built with your Facebook App ID + Client Token (Integrate step); without them every call answers `not_configured`.

**Returns:** `facebookLogin(permissionsCsv, callbackId)` resolves `window.__appmintReplies[callbackId]`; with an empty `callbackId` the answer arrives as the `appmint:facebook-login` event. `getFacebookAccessToken()` returns the token JSON or `""`. `facebookLogEvent(name, valueToSum, paramsJson)` returns `{ok, name, dropped}` as JSON text (`valueToSum` is a number as text, or `""`). **Needs:** Facebook Login switched on in the build.

```js
window.addEventListener('appmint:facebook-login', (e) => {
  if (e.detail.ok) console.log('token', e.detail.accessToken);
  else if (!e.detail.cancelled) console.warn(e.detail.error);
});
WebToApk.facebookLogin('public_profile,email', '');

var t = WebToApk.getFacebookAccessToken();          // '' when signed out
var logged = JSON.parse(WebToApk.facebookLogEvent('Subscribe', '4.99', JSON.stringify({ plan: 'monthly' })));
WebToApk.facebookLogout();
```

**Notes:** Implemented in FacebookBridge.kt without any Facebook SDK: login is Facebook's manual web flow in a browser tab, App Events go to Facebook's App Events Graph API.

