Reads the landing pages you name and logs specific conversion fixes to a Google Sheet, one row per tip.
Uses
Google Sheets
OpenAI
Review landing pages with AI and log the fixes
Give it a list of landing pages and a line on what they sell and who they are for, then run it whenever you want a review. Each page is fetched and read by the AI the way a conversion specialist would read it, looking for a buried or vague call to action, messaging that never says what the product is, layout that puts competing links in front of the offer, missing proof, and forms that ask for too much.
You end up with a tab named 'Landing page reviews' in your Google Sheet, with one row per finding: the date, the page, the area, what is wrong in the page's own words and the change to make. Rows are only ever added, so the tab becomes a record of what you were told and when. A page that will not load is reported and skipped rather than reviewed as if it were fine, and one failed page does not stop the rest.
You need a Google Sheet to write to; the tab and its headings are created on the first run.
pageUrls to blank.Set pageUrls to blank.offerAndAudience to blank.Set offerAndAudience to blank.reportSheetUrl to blank.Set reportSheetUrl to blank.reportTabName to Landing page reviews.Set reportTabName to Landing page reviews.pageCharacterLimit to 18000.Set pageCharacterLimit to 18000.tabIsNew to false.Set tabIsNew to false.createTabErrorIf a step below fails, save the error as createTabErrorreportTabName in reportSheetUrl.Create the tab reportTabName in reportSheetUrl.tabIsNew to true.Change tabIsNew to true.createTabError.message).Show in the output: The '@reportTabName' tab is already there, so this run adds to it. (createTabError.message).tabIsNew is yesIf tabIsNew is yesreportTabName in reportSheetUrl.Add a row to reportTabName in reportSheetUrl.pageUrls with "Split pageUrls with
replaced by , by , and save it as pageList.pagesReviewed to 0.Set pagesReviewed to 0.tipsWritten to 0.Set tipsWritten to 0.pageEntry in pageList:For each pageEntry in pageList:pageEntry and save it as pageUrl.Trim pageEntry and save it as pageUrl.pageUrl is emptyIf pageUrl is emptypageText to blank.Set pageText to blank.pageReached to false.Set pageReached to false.fetchErrorIf a step below fails, save the error as fetchErrorpageUrl and save it as response.Fetch pageUrl and save it as response.pageReached to response.ok.Change pageReached to response.ok.response.body and save it as pageText.Trim response.body and save it as pageText.pageUrl - fetchError.message.Show in the output: Could not open pageUrl - fetchError.message.pageReached isn't yes or pageText is emptyIf pageReached isn't yes or pageText is emptypageUrl because it did not return a readable page.Show in the output: Skipped pageUrl because it did not return a readable page.pageText to pageCharacterLimit characters (keeping words whole) and save it as pageExcerpt.Shorten pageText to pageCharacterLimit characters (keeping words whole) and save it as pageExcerpt.reviewPrompt to You are a conversion rate optimisation specialist reviewing one landing page. Give the specific, actionable notes you would give a client, not a score and not general advice that would fit any page.Set reviewPrompt to You are a conversion rate optimisation specialist reviewing one landing page. Give the specific, actionable notes you would give a client, not a score and not general advice that would fit any page.
What this page sells, who it is for, and what counts as a conversion:
offerAndAudience
Look for the things that actually lose conversions on this page:
- Call to action: is the main action obvious, above the fold, and worded as a benefit rather than 'Submit' or 'Learn more'?
- Messaging: within five seconds, does the page say what this is, who it is for, and why it beats the alternative?
- Layout: what gets between a visitor and the action - competing links, walls of text, the offer buried below three scrolls?
- Trust: is there proof a stranger would believe - named customers, numbers, guarantees, pricing that is actually shown?
- Forms: how many fields, and is every one of them worth the drop-off?
Reply with at most 8 findings, one per line, and nothing else. No numbering, no bullet characters, no introduction and no closing summary. Each line is exactly three parts separated by the pipe character:
Area | What is wrong | What to change
Area must be one of: Call to action, Messaging, Layout, Trust, Forms. Quote the page's own wording when you name a problem, and make the change concrete enough to hand straight to a designer. Leave out anything you cannot see evidence for in the page below.
Page address: pageUrl
Page source below as raw HTML. Read the visible copy and the form and link markup; ignore script blocks, style blocks and tracking tags.
pageExcerpt.findings to blank.Set findings to blank.reviewErrorIf a step below fails, save the error as reviewErrorreviewPrompt. Save it as review.Ask OpenAI: reviewPrompt. Save it as review.review.response_text and save it as findings.Trim review.response_text and save it as findings.pageUrl - reviewError.message.Show in the output: Could not review pageUrl - reviewError.message.findings is emptyIf findings is emptypageUrl, so nothing was written for it.Show in the output: No optimisation tips came back for pageUrl, so nothing was written for it.reviewedOn.Get today's date and save it as reviewedOn.findings by a new line and save it as findingLines.Split findings by a new line and save it as findingLines.rowsForThisPage to 0.Set rowsForThisPage to 0.findingLine in findingLines:For each findingLine in findingLines:findingLine by | and save it as parts.Split findingLine by | and save it as parts.parts is greater than or equal to 3If the length of parts is greater than or equal to 3reportTabName in reportSheetUrl.Add a row to reportTabName in reportSheetUrl.rowsForThisPage.Add 1 to rowsForThisPage.tipsWritten.Add 1 to tipsWritten.rowsForThisPage is 0If rowsForThisPage is 0reportTabName in reportSheetUrl.Add a row to reportTabName in reportSheetUrl.tipsWritten.Add 1 to tipsWritten.pagesReviewed.Add 1 to pagesReviewed.pagesReviewed as text landing page(s) and wrote tipsWritten as text tip(s) to the '@reportTabName' tab.Show in the output: Reviewed pagesReviewed as text landing page(s) and wrote tipsWritten as text tip(s) to the '@reportTabName' tab.