Writes each planned topic with AI, saves it to WordPress as a draft, and records the link in your sheet.
Uses
Google Sheets
OpenAIWordPress
Turn a content plan into WordPress drafts
Once a day, the topics on your content plan spreadsheet are worked through a few at a time. For each topic not yet written, AI drafts the post body for the audience and house style you describe, taking any angle noted on the row, and the post is created in WordPress with the topic as its title.
You end up with drafts waiting in WordPress and a 'Drafted Posts' tab in the same spreadsheet recording each topic, its post id, its link and the date. Nothing is ever published: every post is saved as a draft for you to open, check and publish yourself. Your plan tab is only read, never written to, and the record tab is only ever appended to, so a later run never drafts the same topic twice. A topic whose draft or WordPress call fails is left unrecorded and picked up on the next run.
Your plan tab needs a column headed 'Topic', and can carry an optional 'Angle' column with extra direction for each post.
planSpreadsheetUrl to blank.Set planSpreadsheetUrl to blank.planTabName to blank.Set planTabName to blank.audienceAndStyle to blank.Set audienceAndStyle to blank.draftLogTabName to Drafted Posts.Set draftLogTabName to Drafted Posts.maxNewDraftsPerRun to 5.Set maxNewDraftsPerRun to 5.draftLogTabErrorIf a step below fails, save the error as draftLogTabErrordraftLogTabName in planSpreadsheetUrl.Create the tab draftLogTabName in planSpreadsheetUrl.draftLogTabError as text.Show in the output: Did not create the '@draftLogTabName' tab, which is expected once it exists: draftLogTabError as text.planSpreadsheetUrl. Save it as draftLog.Read the rows of planSpreadsheetUrl. Save it as draftLog.draftLog.headers is emptyIf draftLog.headers is emptydraftLogTabName in planSpreadsheetUrl.Add a row to draftLogTabName in planSpreadsheetUrl.alreadyDrafted.Start an empty list and save it as alreadyDrafted.loggedPost in draftLog.rows:For each loggedPost in draftLog.rows:loggedTopicErrorIf a step below fails, save the error as loggedTopicErrorloggedPost.Topic in lowercase to the end of alreadyDrafted and save it as alreadyDrafted.Add loggedPost.Topic in lowercase to the end of alreadyDrafted and save it as alreadyDrafted.planSpreadsheetUrl. Save it as plan.Read the rows of planSpreadsheetUrl. Save it as plan.newDrafts to 0.Set newDrafts to 0.plannedPost in plan.rows:For each plannedPost in plan.rows:newDrafts is greater than or equal to maxNewDraftsPerRunIf newDrafts is greater than or equal to maxNewDraftsPerRunReached this run's limit of new drafts. The rest of the plan is picked up on the next run..Show in the output: Reached this run's limit of new drafts. The rest of the plan is picked up on the next run..topic to blank.Set topic to blank.topicErrorIf a step below fails, save the error as topicErrorplannedPost.Topic and save it as topic.Trim plannedPost.Topic and save it as topic.topic is emptyIf topic is emptyalreadyDrafted contains topic in lowercaseIf alreadyDrafted contains topic in lowercasetopic.Show in the output: Already drafted, skipping: topic.angle to blank.Set angle to blank.angleErrorIf a step below fails, save the error as angleErrorplannedPost.Angle and save it as angle.Trim plannedPost.Angle and save it as angle.angle to blank.Change angle to blank.brief to Topic: topic.Set brief to Topic: topic.angle isn't emptyIf angle isn't emptybrief to briefChange brief to brief
Angle to take: angle.prompt to You are writing one post for a company blog.Set prompt to You are writing one post for a company blog.
Audience and house style:
audienceAndStyle
brief
Write the finished post body. Return ONLY the body HTML - <h2>, <h3>, <p>, <ul> and <li> tags. Do not include an <h1>, a title line, a code fence, or any commentary before or after the HTML. Aim for 600-900 words, use concrete examples, and do not invent statistics, quotes, customer names, or links.draftHtml to blank.Set draftHtml to blank.writingErrorIf a step below fails, save the error as writingErrordraftHtml.Trim the response text from the OpenAI “Ask OpenAI” step and save it as draftHtml.writingError as text.Show in the output: Could not draft '@topic': writingError as text.draftHtml is emptyIf draftHtml is emptynewPost to nothing.Set newPost to nothing.wordpressErrorIf a step below fails, save the error as wordpressErrortopic. Save it as newPost.Create the post topic. Save it as newPost.draftHtmlwordpressError as text.Show in the output: Could not create the WordPress draft for '@topic': wordpressError as text.postUrl to blank.Set postUrl to blank.postLinkErrorIf a step below fails, save the error as postLinkErrornewPost.link and save it as postUrl.Trim newPost.link and save it as postUrl.postUrl to blank.Change postUrl to blank.postUrl is emptyIf postUrl is emptydraftLogTabName in planSpreadsheetUrl.Add a row to draftLogTabName in planSpreadsheetUrl.topic in lowercase to the end of alreadyDrafted and save it as alreadyDrafted.Add topic in lowercase to the end of alreadyDrafted and save it as alreadyDrafted.newDrafts.Add 1 to newDrafts.