npm package: @onside/install-widget
Description: Onside install button widget for partner landings
Latest version: 1.1.3
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# Onside Install Widget

## Install Flow Contract (Target Behavior)

This section defines the expected runtime behavior of the install package.
It is the source of truth for UX + analytics for partner integrations.

### Scenario Matrix

| Scenario | Condition | Button text | Modal | GTM event(s) | Action |
| --- | --- | --- | --- | --- | --- |
| Direct install | `canInstall === true` and `isEligible !== false` and install URL loaded | `Install Onside` | none | `install_button_click` with `event_type=install_click` (or `ios_18_6_plus`) | Redirect to install URL |
| Browser unsupported on iOS | `shouldGoToSafari === true` | `Install Onside` | `go_to_safari` instruction modal | `go_to_safari.opened` | Block redirect until user opens supported browser |
| iOS version unsupported | `shouldUpdateIOS === true` | `Install Onside` | `update_ios` instruction modal | `update_ios.opened` | Block redirect until iOS update |
| Android device | `isAndroid === true` | `Onside is for iPhone and iPad` | `is_android` info modal | `is_android.opened` | Block install |
| Region not eligible | `isEligible === false` | `Install Onside` + caption `Only available in the EU. Install from an eligible region.` | none | optional `install_button_click` with `event_type=not_eligible` | Allow install attempt (system flow may still permit install) |
| Install API error | install URL fetch failed after retries | `Install Onside` | none | optional `install_button_click` with `event_type=api_error` | Show inline error only; fallback modal/retry flow is not required for current release |

### Notes

- Required analytics context in GTM payload: `location`, `page`, `onside_token`, `attribution_token`, `platform`, `browser`.
- Optional additive device fields (for richer analytics/debug): `iosDeviceClass`, `isInAppBrowser`, `browserDetail`.
  Existing required fields remain backward-compatible.
- If a modal is shown, redirect must not happen in the same click action.
- `onside_token` cookie must be present before requesting install URL.

## Delivery Modes

The button is delivered in two supported ways:

1. React package (`@onside/install-widget`)
2. CDN script (IIFE widget, no React required in host app)

### 1) React package

Install dependencies:

```bash
pnpm add @onside/install-widget react react-dom
```

Usage:

```tsx
import { InstallAppButton, InstallWidgetProvider } from "@onside/install-widget";
import "@onside/install-widget/styles.css";

function App() {
  return (
    <InstallWidgetProvider>
      <InstallAppButton />
    </InstallWidgetProvider>
  );
}
```

Mount `InstallWidgetProvider` once per page. It hosts all install modals and supports multiple `InstallAppButton` instances.
For per-button attribution, set `id` and `location` on each button (`button_id` + `location` in analytics events).

Optional custom analytics callback:

```tsx
import { InstallAppButton, InstallWidgetProvider } from "@onside/install-widget";
import "@onside/install-widget/styles.css";

function App() {
  return (
    <InstallWidgetProvider>
      <InstallAppButton
        customAnalytics={{
          onEvent: (event) => {
            // full enriched event payload (event_name, event_properties, url, etc.)
            console.log(event);
          },
        }}
      />
    </InstallWidgetProvider>
  );
}
```

Core modules can be imported via subpaths (without the UI layer):

```ts
import { useInstallUrl } from "@onside/install-widget/hooks";
import {
  getDeviceInfo,
  resolveInstallConditions,
  getInstallUrl,
} from "@onside/install-widget/utils";
```

Style customization:

```tsx
<InstallAppButton
  className="w-full"
  captionClassName="opacity-80"
  styleVars={
    {
      "--onside-btn-bg": "#111827",
      "--onside-btn-bg-hover": "#1f2937",
      "--onside-btn-text": "#ffffff",
      "--onside-btn-radius": "16px",
      "--onside-btn-px": "24px",
      "--onside-btn-py": "14px",
      "--onside-btn-font-size": "16px",
      "--onside-caption-color": "rgba(17,24,39,0.7)",
      "--onside-caption-size": "12px",
      "--onside-caption-line-height": "16px",
    }
  }
/>
```

### 2) CDN script (no React in host)

Build artifacts are produced in `dist/` (widget script) and loaded directly on the partner page.

Example:

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Onside Widget</title>
</head>
<body>
  <div class="install-button"></div>
  <script
    src="https://<your-cdn>/provider-widget.iife.js"
    data-selector=".install-button"
    data-css-href="https://<your-cdn>/onside-install-widget.css"
  ></script>
</body>
</html>
```

Required script attributes:

- `data-selector`: CSS selector of target container.
- `data-css-href`: URL to widget stylesheet.

### CDN media manifest (images/video)

Media paths are resolved by `cdn("/path/to/file")` using a local manifest snapshot:

- source manifest URL: `https://cdn.onside.io/assets/onside-install-widget/manifest.json`
- generated file in repo: `src/generated/cdnManifest.ts`

Update the local snapshot before release:

```bash
pnpm run sync:cdn-manifest
```

## Release Preflight

Run before publishing a new package version:

```bash
pnpm run sync:cdn-manifest
pnpm run lint
pnpm run build:lib
```

QA artifacts/checklists:

- `docs/checklists/install-flow-release-checklist.md`
- `docs/checklists/install-flow-qa-report-template.md`
- `docs/checklists/install-flow-qa-report-draft.md`

## Release Flow (GitHub + npm)

1. Add a changeset in feature PRs that affect package behavior:
   - `pnpm changeset`
2. Merge PRs into `main`.
3. `Release` workflow opens/updates a release PR with version/changelog changes.
4. Merge the release PR.
5. `Release` workflow publishes the package to npm via OIDC trusted publishing (no npm token in GitHub secrets).

## Troubleshooting

- If `sync:cdn-manifest` fails locally due to network restrictions, run the manual workflow:
  - GitHub Actions -> `Sync CDN Manifest` -> `Run workflow`
- If manifest did not change, no PR is created by the workflow.

### Packaging notes

- React package output is in `dist-lib/`:
  - `install-package.js` (ESM)
  - `install-package.cjs` (CJS)
  - `install-package.d.ts` (types)
- Script widget output is in `dist/`:
  - `provider-widget.iife.js`