When ReviewPro’s Scheduled Reports Fell Short: Building a Fully Automated Workflow with Google Apps Script
I recently needed to automate the retrieval of guest review reports from ReviewPro. At first glance, the platform’s scheduled reporting feature looked like the perfect solution. However, after implementing it, I discovered two limitation(s).
- Instead of sending the actual Excel report as an attachment — or even providing a direct download URL — the scheduled report emails contain an HTML page with a download button. Since the download link is generated dynamically, the URL cannot simply be extracted and reused by an automation script.
- ReviewPro blocks the Google App Script UrlFetchApp request by returning the HTTP 403 code.
To make it automatic, I need to solve both of the above problems, right!
The scope of this article is to show the URL generation process and why use lightweight API if you are using google app script.
Lets talk about how I automated it completely!
Step 1 — Extract the Job ID
The initial ReviewPro report URL contains a jobId and two (2) other parameter(s).
Example:
...&jobId=120660963&lang=en&userId=...Google App Script
var html = message.getBody();
// Find download link
var match = html.match(/<a\b[^>]*href="([^"]+)"[^>]*>\s*Download Your Report Now\s*<\/a>/i);
if (!match) return;
var downloadUrl = match[1];
var queryEndpointParam = getQueryParam_(downloadUrl, "endpoint");
var queryHashParam = getQueryParam_(downloadUrl, "hash");
var jobId = getQueryParam_(downloadUrl, "jobId");
Logger.log("jobId: " + jobId);
var newDownloadUrl = `https://app.reviewpro.com/api/report-server/download/anonymousReport/orm_tracking_xls/${jobId}?endpoint=${queryEndpointParam}&hash=${queryHashParam}&lang=en`;
var generatedReportId = fetchFromCloudRunAPI_(newDownloadUrl);
Logger.log(generatedReportId);
...
..
var your_file_name = "....";
var finalDownlodUrl = `https://app.reviewpro.com/api/report-server/download/${generatedReportId}?fileName=${your_file_name}Step 2 — Generate the Anonymous Report URL
Using the Job ID, construct the anonymous download endpoint.
Get Sharif Bhuiyan’s stories in your inbox
Join Medium for free to get updates from this writer.
Structure:
https://app.reviewpro.com/api/report-server/download/anonymousReport/orm_tracking_xls/{JOB_ID}?endpoint=...&hash=...This endpoint does not download the report. Instead, it creates a temporary report instance.
Step 3 — Generate the Report ID
Opening the anonymous URL returns a long identifier.
Example:
164324xxxxx_xxxxxxxxxxxxxxxxThis ID represents the actual generated report. Think of it as a temporary token used for downloading the final file.
Step 4 — Download the Report
Finally, use the generated Report ID.
Structure:
https://app.reviewpro.com/api/report-server/download/{REPORT_ID}?fileName=ABC_Reviews.xlsxThis URL immediately downloads the Excel report…boom! Now it is very easy to automate.
Why Google Apps Script Alone Wasn’t Enough
Initially, I planned to automate everything using Google Apps Script. However, there was another obstacle which is …
Google’s backend infrastructure acts as a forward proxy (X-Forwarded-For), appending the internal Google routing IP addresses to this header
and ReviewPro doesn’t like it. Hence it returns HTTP 403 error and to solve it, you need to use another API layer to call it.
Conclusion
Although ReviewPro provides scheduled reports, the existing workflow still requires manual interaction before the report can be downloaded.
By understanding the underlying request flow and reverse-engineering the report generation process, it was possible to build a fully automated solution using Google Apps Script and a lightweight API.
The result is an end-to-end automation pipeline that eliminates repetitive manual work while remaining flexible enough to adapt if the platform evolves!





