Skip to content

ZReviewTender fetches app reviews from the App Store and Google Play Console using the new Stability API, and resends them to Slack or integrates with your workflow.

License

Notifications You must be signed in to change notification settings

ZhgChgLi/ZReviewTender

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

ZReviewTender

ZReviewTender fetches app reviews from the App Store and Google Play Console using the new Stability API, and resends them to Slack or integrates with your workflow.

ZReviewTender

Features

  • Supports fetching App Store reviews for iOS apps and Mac OS apps
  • Supports fetching Google Play Console reviews for Android apps
  • Resends the newest reviews to a specified Slack channel
  • Supports auto-translating review content to your language using Google Translate
  • Supports auto-logging reviews to Google Sheets or Asana task
  • Offers flexible extensions so you can develop your own processor (a.k.a. plugin) to suit your workflow
  • Provides a lightweight implementation that only logs the latest review timestamp, rather than saving all reviews in local storage
  • Supports filtering, allowing you to add custom filter conditions to filter out the reviews you don't need
  • Based on official APIs (AndroidpublisherV3 and the brand new AppStoreConnect API), eliminating the need for workarounds or dealing with session expired problems
  • Quickly deployable with the Github Repo Template/Github Action
  • 100% Ruby@RubyGem

Result

1_wlGNbHopjPwFsP8j9LpKcw

Compare with similar services

ZReviewTender Appreviewbot.com Reviewbot.io Aappbot.co Appfollow.io Appfigures.com
Pricing for 2 Apps (Android & iOS) Forever Free No limit $11.99/month $5/month $39/month $0 $7.99/month
Service Type PaaS SaaS SaaS SaaS SaaS SaaS
Stability & Immediacy High High untested untested Low untested
Countries/Languages Limit No limit No limit 5 No limit No limit No limit
Reviews Monitoring (resend to Slack)
Reviews Auto-Translation ✅ Powered by GoogleTranslate ❌ (not available for basic plan) ✅ (300 Reviews/month) ❌ (not available for free plan)
Reviews Monitoring Customized Filter
Customized Integration
Reply to reviews ❌ (not available for small plan) ❌ (not available for free plan)
Reviews Analytics or Reporting ❌ (not available for basic plan)

Setup - Only need Default Proceesor(Slack/Filter/Google Translate)

The entire setup process takes about 30 minutes, but only needs to be set up once. Unless the credentials and keys are changed, it can run stably and for free forever. 🚀🚀🚀🚀🚀


Buy me a coffee ❤️❤️❤️

bmc-button

If this project has helped you, feel free to sponsor me a cup of coffee, thank you.


Deploy With Github Action

image

Deploy with Gitub Repo Template 🚀🚀🚀

  • no need host/server ✅
  • no need environment requirement ✅
  • no engineering background knowledge ✅
  • only need configuration ✅
  • total free ✅

Github Action Proivde 2,000+ mins/month for free. ZReviewTender will cost ~= 30s per time, default run every 6 hours will cost 4 times/day * 30s/per time * 30days = 60 mins/month

⚠️️️️️ MUST CREATE PRIVATE REPO, TO KEEP YOUR CREDENTIAL FILES SAFE. ⚠️️️️️

Docker

  1. make sure has Docker on your system.
  2. git clone this repo git clone https://github.com/ZhgChgLi/ZReviewTender
  3. cd /ZReviewTender
  4. build docker image docker build -t zreviewtender:latest --build-arg CRON_SETTING="*/30 * * * *" --build-arg ZREVIEWTENDER_COMMAND="-r" .
    • CRON_SETTING = crontab schedule setting
    • ZREVIEWTENDER_COMMAND = ZReviewTender Command (Refer to the configuration block down below.)
  5. Refer to the configuration block down below and finish the configuration.
  6. run docker docker run -v ./:/usr/src/app zreviewtender
  7. have fun!

Using Gem

If you are familiar with ruby:

  1. make sure you have Ruby in your environment (I use 2.6.5p114)
  2. make sure you have Bundle in your environment (I use 2.3.13)
  3. type gem install ZReviewTender in terminal

If you are NOT familiar with ruby:

  1. MacOS comes with a System Ruby pre-installed, but we are NOT Recommend to use that, using rvm/rbenv's Ruby instead.
  2. install rbenv or rvm to manage Ruby environment
  3. install Ruby through rbenv/rym (you can install ruby version 2.6.X)
  4. change the systme ruby to rbenv/rvm's Ruby
  5. type which ruby in terminal to make sure current Ruby is NOT /usr/bin/ruby
  6. type gem install ZReviewTender in terminal

Setup - Manually(You can create your own Processor)

  1. Clone this repo
  2. Setup ruby environment
  3. run bundle install
  4. execute with bundle exec bin/ZReviewTender

Configuration

ZReviewTender uses yaml file to config Apple/Google Review Bot Setting.

[Recommended] use ZReviewTender -i generator apple.yml & android.yml config yml files.

Apple (iOS/macOS App)

  1. Reference the apple.example.yml example config yaml file. (Please rename apple.example.yml to apple.yml if you've downloaded from reference.)
  2. fill configuration in yaml file:

Go to App Store Connect -> Keys -> App Store Connect API

appStoreConnectIssueID:

1_FsgHMeCGLVbuetBC4gIP_w

appStoreConnectP8PrivateKeyID & appStoreConnectP8PrivateKeyFilePath:

Create a new API Key:

1_xBtkRFEKO2xHU26TMdXJZQ

  • Name: ZReviewTender
  • Access: App Manager

1_DvjiO3IkHEiPXp0M_dnnww

  • appStoreConnectP8PrivateKeyID: Key ID
  • appStoreConnectP8PrivateKeyFilePath: /AuthKey_XXXXXXXXXX.p8, Download API Key and placed it to /config/ folder (releated path with config yml file)

appID:

1_Ov2pyW9anRVqNCpbxhHtJQ

appID: App Store Connect -> App Store -> General -> App Information -> Apple ID

  1. after filled out configuration in yaml file, rename apple.example.yml to apple.yml

Use Authenticating as a service accountAuthenticating as a service account for Google Releated Service

  • follow the steps of Creating a service account in offcial documentation, to create a service account of GCP and download the GCP JSON Private Key.
  • make sure the service account have the right access you need (e.g. Google Translate/Google Ancdroid Publisher API/Google Sheet...)

Google Play Console (Android App)

  1. Download the android.example.yml config yaml file. (Please rename android.example.yml to android.yml if you've downloaded from reference.)
  2. fill configuration in yaml file:

packageName:

1_XRzKNGhVbBef7Hl9XPcaWw

packageName: find Android App packageName in Google Play Console -> Dashboard -> App

playConsoleDeveloperAccountID & playConsoleAppID:

find in Google Play Console -> Dashboard -> App -> Page URL:

https://play.google.com/console/developers/**playConsoleDeveloperAccountID**/app/**playConsoleAppID**/app-dashboard

keyFilePath:

Follow the GCP Started Document to created a Google Cloud Project Service Account and linked it to your Google Play Console, enable Google Play Android Developer API in Google Play Console -> Setup -> API Access.

1_yQhAVOuF_CvM49Vayl40zA

1_-AKvlk9P6R0YkuZwsXJaLA

  • make sure the service account have the right access

keyFilePath: /gcp_key.json the key path of GCP JSON Private Key, placed it to /config/ folder (releated path with config yml file).

Default Processor

FilterProcessor

  • class: FilterProcessor, no need to chane, it's point to lib/Processors/FilterProcessor.rb
  • enable: true/false enable this Processor or Not
  • keywordsInclude: ["KEYWORD1","KEYWORD2"…] filter out the Review that contains those keywords
  • ratingsInclude: [1,2…] 1~5 filter out the Review that contains rating
  • territoriesInclude: ["zh-hant","TWN"…] filter out the Review that from those territories (Territor(TWN/JPN...) for Apple / Language(zh-hant,en...) For Android)

GoogleTranslateProcessor

  • class: GoogleTranslateProcessor, no need to chane, it's point to lib/Processors/GoogleTranslateProcessor.rb
  • enable: true/false enable this Processor or Not
  • googleTranslateAPIKeyFilePath: /gcp_key.json Google Translate GCP Service Account JSON Private Key File Path *.json,placed it to /config/ folder (releated path with config yml file)
  • make sure the service account have the right access(Google Translate API)
  • googleTranslateTargetLang: zh-TW Target translated language
  • googleTranslateTerritoriesExclude: ["zh-hant","TWN"…] (Territor(TWN/JPN...) for Apple or Language(zh-hant,en...) For Android review that didn't need to translate.

SlackProcessor

  • class: SlackProcessor, no need to chane, it's point to lib/Processors/SlackProcessor.rb
  • enable: true/false enable this Processor or Not
  • slackTimeZoneOffset: +08:00 timezone of display review created time
  • slackAttachmentGroupByNumber: 1 specify how many Reviews will group by in same Slack Message (in Attacment)
  • slackBotToken: xoxb-xxxx-xxxx-xxxx Slack Bot Token
  • slackBotTargetChannel: CXXXXXX Channel ID (Not Channel Name), and you need to add Slack Bot to this Channel
  • slackInCommingWebHookURL: https://hooks.slack.com/services/XXXXX the old send message to slack way, will deprecated.
Please note, this is a legacy custom integration - an outdated way for teams to integrate with Slack. These integrations lack newer features and they will be deprecated and possibly removed in the future. We do not recommend their use. Instead, we suggest that you check out their replacement: Slack apps.

ZReviewTender will use slackBotToken by default.

1_D1kt_6jH0UaJo2kvf9l5Qw (1)

1_UjE_LxtZ0adwS6tr2-vgbw

GoogleSheetProcessor

  • class: GoogleSheetProcessor, no need to chane, it's point to lib/Processors/GoogleSheetProcessor.rb
  • enable: true/false enable this Processor or Not
  • googleSheetAPIKeyFilePath: /gcp_key.json Google Sheet GCP Service Account JSON Private Key File Path *.json,placed it to /config/ folder (releated path with config yml file)
  • make sure the service account have the right access(Google Translate API)
  • googleSheetTimeZoneOffset: +08:00 timezone of display review created time
  • googleSheetInsertStyle.type: "append" # Google Sheet Insert type, append or insert
  • googleSheetInsertStyle.at: 0 # required if type is insert, where index should insert at
  • googleSheetInsertStyle.sheetID: null # required if type is insert, the sheet ID, you can get it on google sheet url: e.g. https://docs.google.com/spreadsheets/d/googleSpreadsheetID/edit#gid=sheetID
  • googleSheetInsertStyle.sheetName: "Sheet1" # required if type is append, a.k.a google sheet tab name
  • values: [] # Columns Data you can uses magic variable below to compose string.
%TITLE% for review's title
%BODY% for review's content
%RATING% for review's rating 1~5
%PLATFORM% for review's platform Apple or Android
%ID% for review's ID
%USERNAME% for review's reviewer username
%URL% for link to review
%TERRITORY% for review's territory (language for android e.g. zh-Hant, en)
%APPVERSION% for review's reviewer app version
%CREATEDDATE% for review's created date
  • keywordsInclude: ["KEYWORD1","KEYWORD2"…] filter out the Review that contains those keywords you want's log to google sheet
  • ratingsInclude: [1,2…] 1~5 filter out the Review that contains rating you want's log to google sheet
  • territoriesInclude: ["zh-hant","TWN"…] filter out the Review that from those territories you want's log to google sheet (Territor(TWN/JPN...) for Apple / Language(zh-hant,en...) For Android)

*make sure you have add service account to your google sheet collaborate with edit permission.

Custom Processor

  1. Clone this repo project (due to ZReviewTedner is a completely Gem, you can't modify it dynamically)
  2. Reference Processor.rb, make a copy and devlop the feature you want

initialize

  • config: config yml parameter
  • configFilePath: config yml file path
  • baseExecutePath the path that user execute ZReviewTender

processReviews(reviews, platform)

  • Input Function
  • you will receive latest reviews list, you can decide what you want to do, e.g. transform or filter...
  • Review Struct: lib/Models/Review.rb
  • Remember return the result reviews, for next Processor uses
  1. Add your Processor & Processor Parameter needed to config.yml, processors: section
  2. Test & Run!
  3. Done!

*processors are data flow chain and sort sensitive.

If you don't need Some Processor (like Google Translate Processor)

  • set enable to false or just remove that Processor Setting Block in config yml

Usage

if you're not install with Gems, you should use bundle exec ruby bin/ZReviewTender to excute.

Generate config yml file

ZReviewTender -i

will generate apple.yml and android.yml in config/ folder.

Check Both Apple & Android App's latest Reviews

ZReviewTender -r

will uses apple.yml and android.yml in config folder.

Check Both Apple & Android App's latest Reviews, specify Config YAML file path

ZReviewTender --run=CONFIG_FOLDER

Check Apple App's latest Reviews

ZReviewTender -a

will uses apple.yml in config folder.

Check Apple App's latest Reviews, specify Config YAML file path

ZReviewTender --apple=PATH_TO_APPLE_CONFIG_YAML_FILE

Check Android App's latest Reviews

ZReviewTender -g

will uses android.yml in config folder.

Check Android App's latest Reviews, specify Config YAML file path

ZReviewTender --googleAndroid=PATH_TO_ANDROID_CONFIG_YAML_FILE

Clean last check timestamp log(back to init state)

ZReviewTender -d

Show current ZReviewTender version

ZReviewTender -v

Upgrade ZReviewTender to latest release version(only RubyGem)

ZReviewTender -n

Init (first time execute)

1_62VO8mbJWxXHSeFo3fEUog

you will received an init success message in your Slack Channel!

latestCheckTimestamp folder & execute.log:

1_U8vjWSHvY2RzUBcUbQoBvQ

ZReviewTender will also created latestCheckTimestamp/Apple, latestCheckTimestamp/Android to log ZReviewTender latest checked Review Timestamp and created execute.log for log excute error.

image

Setup a crontab schedule job to excute(Check latest Review & Process) periodicity

  • You could use crontab or any schedule service to execute ZReviewTender periodicity
  • e.g. in crontab: 15 */6 * * * ZReviewTender -r
  • please note that, google api only allow retrieve the reviews that users have created or modified within the last week, so could not set the time period more than one week.

image

Github Action

image

ZReviewTender App Reviews Automatic Bot

name: ZReviewTender
on:
  workflow_dispatch:
  schedule:
    - cron: "15 */6 * * *" #check new review every 6 hour.

jobs:
  ZReviewTender:
    runs-on: ubuntu-latest
    steps:
    - name: ZReviewTender Automatic Bot
      uses: ZhgChgLi/ZReviewTender@main
      with:
        command: '-r'

you can change command to others ZReviewTender's command.

⚠️️️️️ Attention

⚠️️️️️ MUST KEEP YOUR CREDENTIAL FILES SAFE, DO NOT EXPOSE ON THE INTERNET. ⚠️️️️️

Disclaimer

This repository is for research purposes only, the use of this code is your responsibility.

  • Code authors take NO responsibility and/or liability for how you choose to use any of the source code available here.
  • By using any of the files available in this repository, you understand that you are AGREEING TO USE AT YOUR OWN RISK.
  • ALL files available here are for EDUCATION and/or RESEARCH purposes ONLY.

Who is using

pinkoi

Pinkoi.com is Asia's leading online marketplace for original design goods, digital creations, and workshop experiences.

About

Other works

Swift Libraries

  • ZMarkupParser is a pure-Swift library that helps you to convert HTML strings to NSAttributedString with customized style and tags.
  • ZPlayerCacher is a lightweight implementation of the AVAssetResourceLoaderDelegate protocol that enables AVPlayerItem to support caching streaming files.
  • ZNSTextAttachment enables NSTextAttachment to download images from remote URLs, support both UITextView and UILabel.

Integration Tools

  • ZReviewTender is a tool for fetching app reviews from the App Store and Google Play Console and integrating them into your workflow.
  • ZMediumToMarkdown is a powerful tool that allows you to effortlessly download and convert your Medium posts to Markdown format.
  • linkyee is a fully customized, open-source LinkTree alternative deployed directly on GitHub Pages.

Donate

Buy Me A Coffe

If you find this library helpful, please consider starring the repo or recommending it to your friends.

Feel free to open an issue or submit a fix/contribution via pull request. :)