{"_id":"@dongminyu/react-native-in-app-review","_rev":"9-b86f42e800b99d3bf4de1b83ec0c9ab7","name":"@dongminyu/react-native-in-app-review","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.2":{"name":"@dongminyu/react-native-in-app-review","version":"0.1.2","keywords":["react-native","ios","android"],"author":{"url":"https://github.com/AndrewDongminYoo","name":"Dongmin, Yu","email":"ydm2790@gmail.com"},"license":"MIT","_id":"@dongminyu/react-native-in-app-review@0.1.2","maintainers":[{"name":"andrewdongminyoo","email":"ydm2790@gmail.com"}],"homepage":"https://github.com/AndrewDongminYoo/react-native-in-app-review#readme","bugs":{"url":"https://github.com/AndrewDongminYoo/react-native-in-app-review/issues"},"dist":{"shasum":"8cbff5198fec8065c044e4b05c8780e3791753c2","tarball":"https://registry.npmjs.org/@dongminyu/react-native-in-app-review/-/react-native-in-app-review-0.1.2.tgz","fileCount":32,"integrity":"sha512-UFNtPAJcZs/yP3LLDQYexCJPmn+pPCcSOUyCw2yI7QznAkkrjy3u2wJs6+XJ9NXsePd8brIDXnh26MONkr205g==","signatures":[{"sig":"MEYCIQD/Qo8mJBA7/12a5dbawzOqgV2eEKIKXmJy2sWNBhwc9gIhAJY/CmGKjVniFL8X+s9vqZdRQ3Q8L1jQJkxIhkJKWAyX","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28628},"main":"./lib/module/index.js","types":"./lib/typescript/src/index.d.ts","exports":{".":{"types":"./lib/typescript/src/index.d.ts","source":"./src/index.ts","default":"./lib/module/index.js"},"./package.json":"./package.json"},"gitHead":"2eba0514c1f4ab0950eebee8ad9cb3e1b113d8d2","scripts":{"web":"vite","lint":"eslint \"**/*.{js,ts,tsx}\"","test":"jest","clean":"del-cli android/build example/android/build example/android/app/build example/ios/build lib","example":"yarn workspace react-native-in-app-review-example","prepare":"bob build","build:web":"vite build","typecheck":"tsc"},"_npmUser":{"name":"andrewdongminyoo","email":"ydm2790@gmail.com"},"repository":{"url":"git+https://github.com/AndrewDongminYoo/react-native-in-app-review.git","type":"git"},"workspaces":["example"],"_npmVersion":"11.16.0","description":"The Google Play In-App Review API, App store rating API lets you prompt users to submit Play Store or App store ratings and reviews without the inconvenience of leaving your app or game.","directories":{},"_nodeVersion":"24.18.0","codegenConfig":{"name":"InAppReviewSpec","type":"modules","android":{"javaPackageName":"com.inappreview"},"jsSrcsDir":"src"},"publishConfig":{"registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"yarn@4.11.0","devDependencies":{"jest":"^30.3.0","react":"19.2.3","turbo":"^2.8.21","eslint":"^9.39.4","del-cli":"^7.0.0","prettier":"^3.8.1","@eslint/js":"^9.39.0","typescript":"^6.0.2","@types/react":"^19.2.0","react-native":"0.85.0","@jest/globals":"^30.0.0","@eslint/compat":"^2.0.3","@eslint/eslintrc":"^3.3.5","react-native-web":"~0.21.1","eslint-plugin-ft-flow":"^3.0.11","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","react-native-builder-bob":"^0.41.0","@react-native/jest-preset":"0.85.0","@react-native/babel-preset":"0.85.0","@react-native/eslint-config":"0.85.0"},"peerDependencies":{"react":"*","react-native":"*"},"_npmOperationalInternal":{"tmp":"tmp/react-native-in-app-review_0.1.2_1782958966579_0.9174757091018266","host":"s3://npm-registry-packages-npm-production"},"create-react-native-library":{"type":"turbo-module","tools":["eslint","jest","vite"],"version":"0.62.0","languages":"kotlin-objc"},"deprecated":"Renamed to react-native-in-app-review-newarch"}},"time":{"created":"2026-07-02T02:22:46.412Z","modified":"2026-07-12T09:15:31.815Z","0.1.0":"2026-05-07T10:27:52.129Z","0.1.1":"2026-06-18T13:17:06.252Z","0.1.2":"2026-07-02T02:22:46.745Z"},"bugs":{"url":"https://github.com/AndrewDongminYoo/react-native-in-app-review/issues"},"author":{"url":"https://github.com/AndrewDongminYoo","name":"Dongmin, Yu","email":"ydm2790@gmail.com"},"license":"MIT","homepage":"https://github.com/AndrewDongminYoo/react-native-in-app-review#readme","keywords":["react-native","ios","android"],"repository":{"url":"git+https://github.com/AndrewDongminYoo/react-native-in-app-review.git","type":"git"},"description":"The Google Play In-App Review API, App store rating API lets you prompt users to submit Play Store or App store ratings and reviews without the inconvenience of leaving your app or game.","maintainers":[{"name":"andrewdongminyoo","email":"ydm2790@gmail.com"}],"readme":"# @dongminyu/react-native-in-app-review\n\nA React Native TurboModule that wraps the **Google Play In-App Review API** (Android) and **Apple StoreKit `requestReview`** (iOS), allowing apps to prompt users for ratings and reviews without leaving the app.\n\nBuilt on the New Architecture (TurboModules + Codegen).\n\n## Requirements\n\n|              | Minimum                           |\n| ------------ | --------------------------------- |\n| React Native | 0.76+ (New Architecture required) |\n| Android      | API 24 (Android 7.0)              |\n| iOS          | 10.3                              |\n\n> This library is a **TurboModule** and requires the New Architecture. If your project is still on the Old Architecture, use [MinaSamir11/react-native-in-app-review](https://github.com/MinaSamir11/react-native-in-app-review) instead.\n\n## Installation\n\n```sh\nnpm install @dongminyu/react-native-in-app-review\n# or\nyarn add @dongminyu/react-native-in-app-review\n```\n\n### iOS\n\nRun `pod install` after installation:\n\n```sh\ncd ios && pod install\n```\n\nStoreKit is linked automatically via the podspec — no manual framework addition needed.\n\n### Android\n\nNo additional setup required. `com.google.android.play:review` is declared in the library's `build.gradle` and resolved automatically by Gradle.\n\n> **Requirement**: The in-app review dialog only works on devices with **Google Play Store installed**. It will not appear on emulators without Play Store or on non-Google Android devices.\n\n## API\n\n### `isAvailable(): Promise<boolean>`\n\nReturns `true` when in-app review is supported on the current device. Call this before showing any review-related UI.\n\n```ts\nconst supported = await isAvailable();\n```\n\n| Platform | Returns                                                          |\n| -------- | ---------------------------------------------------------------- |\n| Android  | `true` if Google Play Store (`com.android.vending`) is installed |\n| iOS      | Always `true` — StoreKit is always present on iOS                |\n| Web      | Always `false`                                                   |\n\n---\n\n### `requestReview(): Promise<void>`\n\nAsks the OS to show the native in-app review dialog.\n\n```ts\nawait requestReview();\n```\n\n**Important**: The promise resolving does **not** mean the dialog was shown. The OS decides silently whether to display or suppress the prompt based on rate-limiting and eligibility rules. Your app cannot detect this distinction by design.\n\n| Platform  | Rejects when                                            |\n| --------- | ------------------------------------------------------- |\n| Android   | `requestReviewFlow()` fails — code: `REVIEW_FLOW_ERROR` |\n| Android   | No foreground activity — code: `ACTIVITY_NULL`          |\n| iOS (14+) | No active `UIWindowScene` found — code: `ACTIVITY_NULL` |\n| iOS       | Never rejects for the review prompt itself              |\n\n---\n\n### `openStoreListing(options?): Promise<void>`\n\nOpens the store page directly. Use this as a fallback when `isAvailable()` returns `false`, or as an alternative \"Rate us\" action.\n\n```ts\nawait openStoreListing({ appStoreId: '1234567890' });\n```\n\n| Option       | Type     | Platform | Notes                                      |\n| ------------ | -------- | -------- | ------------------------------------------ |\n| `appStoreId` | `string` | iOS only | Numeric App Store ID — **required on iOS** |\n\n| Platform | Behaviour                                                                                                              |\n| -------- | ---------------------------------------------------------------------------------------------------------------------- |\n| Android  | Opens `market://details?id=<packageName>`, falls back to `https://play.google.com/store/apps/details?id=<packageName>` |\n| iOS      | Opens `itms-apps://itunes.apple.com/app/id<appStoreId>?action=write-review`                                            |\n\n| Rejects with           | Cause                                                          |\n| ---------------------- | -------------------------------------------------------------- |\n| `MISSING_APP_STORE_ID` | iOS — `appStoreId` not provided                                |\n| `INVALID_URL`          | iOS — URL could not be constructed from the given `appStoreId` |\n| `OPEN_URL_FAILED`      | iOS — OS could not open the URL                                |\n| `OPEN_STORE_FAILED`    | Android — both `market://` and `https://` intents failed       |\n| `ACTIVITY_NULL`        | Android — no foreground activity                               |\n\n## Usage\n\n### Recommended pattern\n\n```ts\nimport {\n  isAvailable,\n  openStoreListing,\n  requestReview,\n} from '@dongminyu/react-native-in-app-review';\n\nasync function promptForReview() {\n  const supported = await isAvailable();\n\n  if (supported) {\n    await requestReview();\n    // Note: resolving here does NOT confirm the dialog was shown.\n    // The OS may suppress it silently due to rate-limiting.\n  } else {\n    // Fallback: open the store page directly.\n    // iOS requires your numeric App Store ID.\n    await openStoreListing({ appStoreId: '1234567890' });\n  }\n}\n```\n\n### With error handling\n\n```ts\nimport {\n  openStoreListing,\n  requestReview,\n} from '@dongminyu/react-native-in-app-review';\n\nasync function handleRateUs() {\n  try {\n    await requestReview();\n  } catch (e) {\n    // Rejected on Android when the review flow fails or the app is in background.\n    // Fall back to opening the store page.\n    try {\n      await openStoreListing({ appStoreId: '1234567890' });\n    } catch {\n      // Handle gracefully — the user can still find the app manually.\n    }\n  }\n}\n```\n\n## When to Prompt\n\nThe OS rate-limits review prompts and will silently suppress requests that come too frequently or too early in an app's lifecycle. Prompting at the right moment increases the chance the dialog is actually shown.\n\n**Good moments to call `requestReview()`:**\n\n- After a user completes a key action (finishes a purchase, completes a level, achieves a goal)\n- After several successful sessions — not on the first launch\n- When the user has just experienced a positive outcome\n\n**Avoid calling `requestReview()`:**\n\n- On app launch or in `useEffect` with no user interaction\n- After an error, crash, or frustrating UX moment\n- From a button tap labeled \"Rate us\" — the OS may suppress the native dialog, leaving the user confused. Use `openStoreListing` instead for explicit \"Rate us\" buttons.\n- More than once per user session\n\n## Caveats\n\n### The OS controls whether the dialog appears\n\nBoth Google Play and Apple StoreKit rate-limit review prompts. The limits are approximately:\n\n| Platform | Limit                                                |\n| -------- | ---------------------------------------------------- |\n| iOS      | ~3 times per 365-day period per app                  |\n| Android  | Quota managed by Play Core (not publicly documented) |\n\nOnce the limit is hit, `requestReview()` resolves immediately with no dialog shown. Your app cannot detect this. Design your flow so that the user is not left waiting for a dialog that will never appear.\n\n### Android: real device and Play Store account required\n\nThe Play In-App Review API requires:\n\n1. The device has Google Play Store installed\n2. The user is **signed in to a Google account** on the device\n3. The app is **available on Google Play** (published to at least an internal testing track)\n\nIn development (local debug builds not uploaded to Play Console), `requestReviewFlow()` may fail or the dialog may not appear. Use Google's [FakeReviewManager](https://developer.android.com/guide/playcore/in-app-review/test) for local testing — this library does not expose it directly, so test via the example app pattern with a real internal-track build.\n\n### iOS: Simulator vs real device\n\n| Environment              | Behaviour                                                                                                                         |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |\n| Simulator                | Shows a **mock** dialog that looks identical to the real one. Rate-limiting does not apply.                                       |\n| Real device (debug)      | Rate-limiting applies. Use `Settings > [App Name] > Reset Review Prompt` (if available) or delete and reinstall the app to reset. |\n| Real device (TestFlight) | Real StoreKit prompts, rate-limiting applies.                                                                                     |\n\n### `requestReview` does not guarantee a dialog\n\nDo not tie any app logic to the assumption that `requestReview()` resolving means a rating was submitted or a dialog was shown. The promise only indicates that the OS received the request.\n\n## Platform Notes\n\n| Behaviour                               | Android                          | iOS                                 |\n| --------------------------------------- | -------------------------------- | ----------------------------------- |\n| `isAvailable()`                         | Checks for Play Store            | Always `true`                       |\n| `requestReview()` failure               | Rejects with `REVIEW_FLOW_ERROR` | Never rejects for the prompt itself |\n| `openStoreListing` without `appStoreId` | Uses app package name            | Rejects with `MISSING_APP_STORE_ID` |\n| Rate-limiting                           | Managed by Play Core             | Managed by StoreKit (≈ 3×/year)     |\n| Test environment                        | FakeReviewManager (not exposed)  | Simulator shows mock dialog         |\n\n## Contributing\n\n- [Development workflow](CONTRIBUTING.md#development-workflow)\n- [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)\n- [Code of conduct](CODE_OF_CONDUCT.md)\n\n## License\n\nMIT\n","readmeFilename":"README.md"}