# Add a Share on WhatsApp button that opens your app

> After this guide, a Share on WhatsApp button in your app sends a link made for that user and screen, the friend's tap opens the same screen in your app (or the store first), and the share is counted under WhatsApp.

- Time: About 30 minutes
- You need: A backend you control with a Strait secret key as SECRET_KEY, and a React Native app with the Strait SDK set up
- Works on: Server in Node 18+ (or curl). App code in React Native for Android and iPhone.

Source: https://straitlink.in/docs/recipes/whatsapp-share-links/

This is the share flow a user starts from your app. To send campaign messages from your business number instead, use [WhatsApp Business API templates](https://straitlink.in/docs/recipes/whatsapp-template-links/). Links need the secret key, which must never ship in an app, so the app asks your server for the link, then hands it to WhatsApp's share URL.

## 1. Make the link on your server

One link per user and screen, with the sharer in the destination's query:

```js title="Node: share-link.mjs"
import { randomBytes } from 'node:crypto';
import express from 'express';
import { StraitClient } from '@straitlink/node';

const strait = new StraitClient({ apiKey: process.env.SECRET_KEY, baseUrl: 'https://strait.link' });
const app = express();
app.use(express.json());

// POST /share-link { "productId": "42" } → { "url": "https://…" }
// Put your own auth in front of this: req.user is the signed-in user.
app.post('/share-link', async (req, res) => {
  const productId = String(req.body.productId).replace(/[^\w-]/g, '');
  const userId = String(req.user?.id ?? 'guest').replace(/[^\w-]/g, '');
  const link = await strait.createLink({
    slug: `p${productId}-${randomBytes(4).toString('hex')}`,
    longUrl: `https://shop.example.com/product/${productId}?ref=${userId}`,
    title: 'Look what I found', // the preview card in the chat
    campaign: 'in_app_share',
  });
  res.json({ url: link.shortUrl });
});

app.listen(3000);
```

The same call with curl:

```bash
curl https://strait.link/v1/links \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "slug": "p42-u7", "longUrl": "https://shop.example.com/product/42?ref=u7", "title": "Look what I found", "campaign": "in_app_share" }'
```

**You should see:** `curl -X POST localhost:3000/share-link -H 'Content-Type: application/json' -d '{"productId":"42"}'` answers `{"url":"https://hilltop.strait.link/p42-…"}` with a random ending, and the curl call answers `"shortUrl": "https://hilltop.strait.link/p42-u7"`.

## 2. Check the chat preview and the tap

WhatsApp fetches the link to draw the preview card, and Strait answers its fetcher with the card, never a redirect. Check both without counting a tap:

```bash
curl "https://strait.link/v1/simulate?url=https%3A%2F%2Fhilltop.strait.link%2Fp42-u7&ua=bot" \
  -H "Authorization: Bearer $SECRET_KEY"

curl "https://strait.link/v1/simulate?url=https%3A%2F%2Fhilltop.strait.link%2Fp42-u7&ua=whatsapp-android" \
  -H "Authorization: Bearer $SECRET_KEY"
```

**You should see:** `"decision": "preview"` for the bot, with a `reason` that says it is "counted as a preview, never billed". For `whatsapp-android`: `"inAppBrowser": "whatsapp"`, `"decision": "escape"`, and a `location` that starts `intent://shop.example.com/product/42?ref=u7&strait_click=…`, the one-tap **Open in app** button.

## 3. Open WhatsApp's share URL from the app

WhatsApp's own rule: "To create a link with just a pre-filled message, use `https://wa.me/?text=urlencodedtext`", and the person then picks who to send it to ([WhatsApp Help Center](https://faq.whatsapp.com/5913398998672934)).

```tsx title="React Native: ShareOnWhatsApp.tsx"
import { Button, Linking } from 'react-native';

export function ShareOnWhatsApp({ productId }: { productId: string }) {
  async function share() {
    const res = await fetch('https://api.yourapp.com/share-link', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' }, // add your own auth header
      body: JSON.stringify({ productId }),
    });
    const { url } = await res.json();
    const text = `Look what I found: ${url}?utm_source=whatsapp`;
    await Linking.openURL(`https://wa.me/?text=${encodeURIComponent(text)}`);
  }
  return <Button title="Share on WhatsApp" onPress={share} />;
}
```

The `?utm_source=whatsapp` on the shared URL labels the tap's channel even if the friend opens the link outside WhatsApp. Strait reads it there and doesn't copy it to the destination.

**You should see:** WhatsApp open with a contact list and the message filled in, ending in `https://hilltop.strait.link/p42-…?utm_source=whatsapp`. Opened in a browser, the `wa.me` URL answers `302` to `https://api.whatsapp.com/send/?text=…`.

## 4. Read the sharer when the link opens the app

The destination's query arrives in `e.params`, on a direct open and on the first open after an install:

```ts title="React Native: links.ts"
links.onLink((e) => {
  if (e.matched && e.params?.ref) saveReferrer(e.params.ref); // your own code
});
```

On Android the destination travels through the Google Play install. On iPhone it comes back after an install when [install matching](https://straitlink.in/docs/iphone-install-matching/) is on.

**You should see:** a friend's tap opening the product screen, and `e.params.ref` set to `u7`, including on the first open after installing.

## 5. Count the shares

```bash
curl "https://strait.link/v1/analytics?link=p42-u7&group=channel" \
  -H "Authorization: Bearer $SECRET_KEY"
```

In Node: `await strait.getAnalytics({ link: 'p42-u7', group: 'channel' })`. Leave out `link` and pass `group=link` to compare every shared link, or filter **Dashboard → Analytics** by the `in_app_share` campaign.

**You should see:** after a friend's tap, `"rows": [{ "key": "whatsapp", "taps": 1, … }]`.

## Common errors

- **`401` from Strait.** The server sent the publishable key. Creating links needs a secret key, and the secret key stays on the server.
- **WhatsApp opens with an empty message.** The text wasn't URL-encoded. Wrap it in `encodeURIComponent`, as above.
- **The preview card says "Open in" and your app's name.** That's the default when the link has no `description`. Set `description` and `imageUrl` when you create the link.

## Next steps

- [Send campaign links via WhatsApp Business API templates](https://straitlink.in/docs/recipes/whatsapp-template-links/): messages from your business number.
- [Create links from a React Native app](https://straitlink.in/docs/sdks/react-native/create-links/): the same server pattern with the system share sheet.
