Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 0.3.1

- **Fixed:** Android and React Native 0.3.0 could return an error from `applyCode()` as if it were a normal result, so an app could show a code as applied when it wasn't. Upgrade to 0.3.1, which raises a typed error for unknown, inactive and wrong-environment codes. iOS and Flutter 0.3.0 threw a generic error, and 0.3.1 makes it typed.
- Check HTTP status on every request; non-2xx responses are never treated as success.
- Add `TapAppLinkRedeemError` with codes `unknownCode`, `inactiveCode`, `wrongEnvironment`, `network` and `other`.
- Send `X-TapAppLink-SDK-Version: 0.3.1` on all requests.

## 0.3.0

- Persist install id, tracked flag, attribution id and offer across launches (AsyncStorage optional peer).
Expand Down
88 changes: 87 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ The Play Install Referrer bridge is Android-only. Storing install state only the
## Usage

```ts
import { TapAppLink } from "@tapapplink/react-native";
import {
TapAppLink,
TapAppLinkRedeemError,
} from "@tapapplink/react-native";

TapAppLink.configure({
publicKey: "etk_live_…",
Expand All @@ -52,6 +55,89 @@ Set `debug: true` to log each request, response and stored state. The API key is

Purchases are attributed with billing **webhooks**, not a client `trackPurchase` call.

### Apply a creator code

Show success only when `applyCode` resolves. Map each result to UI state as below. Customers must never see the word "environment".

```ts
type RedeemUi = {
title: string;
detail?: string;
hint?: string;
showCode: boolean;
};

async function redeemForUi(code: string): Promise<RedeemUi> {
try {
const result = await TapAppLink.applyCode(code);
const offerLine =
typeof result.offer === "object" &&
result.offer &&
typeof (result.offer as { creatorName?: string }).creatorName === "string"
? `Offer from ${(result.offer as { creatorName: string }).creatorName}`
: undefined;

if (result.alreadyAttributed === true) {
return {
title: "You're all set",
detail: offerLine,
showCode: false,
};
}

return {
title: "Code applied",
detail: offerLine,
showCode: true,
};
} catch (error) {
if (error instanceof TapAppLinkRedeemError) {
switch (error.code) {
case "unknownCode":
return {
title: "We don't recognise that code. Check it and try again.",
hint: "Codes aren't case sensitive.",
showCode: true,
};
case "inactiveCode":
return {
title: "This code is no longer active.",
hint: "You can still subscribe at the regular price.",
showCode: true,
};
case "wrongEnvironment":
// Developer only. Customers see the unknownCode copy (never "environment").
console.warn(TapAppLinkRedeemError.wrongEnvironmentDevWarning);
return {
title: "We don't recognise that code. Check it and try again.",
hint: "Codes aren't case sensitive.",
showCode: true,
};
case "network":
return {
title:
"We couldn't check your code. Check your connection and try again.",
showCode: true,
};
case "other":
default:
console.warn("TapAppLink applyCode failed", {
code: error.code,
status: error.status,
message: error.message,
});
return {
title:
"We couldn't check your code. Check your connection and try again.",
showCode: true,
};
}
}
throw error;
}
}
```

## Publishing

Maintainers: see [PUBLISHING.md](./PUBLISHING.md) for the CI release tag flow and one-time npm trusted publishing setup.
Expand Down
Loading
Loading