Skip to content

The moment it happens

Turn a document into a blog post you approve by email

Send a PDF to your trigger link and a WordPress draft is written from it; reply "approve" to the email and the post goes live.

Runs
The moment it happens
Apps
Gmail, WordPress
AI
Yes, uses the built-in AI allowance
Access
WordPress write; Gmail gmail.send + gmail.readonly

Send this to your assistant

Create a ClickRuntime automation: when I send a PDF to my trigger link, write a blog post from it, save it as a WordPress draft, email me the link, and publish it when I reply "approve".

Paste it into your assistant. It tells you what it will send or change before it runs live.

First time? Adding ClickRuntime to your assistant takes about two minutes.

Why use it

Why teams use this automation

A charity's programme team writes detailed reports on each project, and the communications lead wants every report to become a blog post for supporters. Turning a twelve-page PDF into an article, then chasing a director for sign-off, means most reports never make it onto the website.

This automation handles both steps. A PDF sent to the trigger link is turned into a draft post by AI and saved in WordPress, and an email with the preview link goes to the approver. When they reply "approve" in the same thread, the post is published, with no need to log in.

What you get out of it

  • Reports reach supporters

    Work already written up for internal use becomes public content. Supporters see what their donations achieve.

  • Sign-off by reply

    Approvers only need to reply to an email. Directors who never log in to WordPress can still approve posts quickly.

  • A clear approval trail

    The approval lives in an email thread, so it is easy to show who approved what and when.

  • Nothing published without a yes

    Posts stay as drafts until the approver replies. Edits can be made in WordPress before approving.

How it works

What happens, step by step

  1. When a PDF arrives at the automation's trigger link, ClickRuntime reads its text and AI writes a blog post from it.

  2. The post is saved as a WordPress draft, and an email with the preview link is sent to the approver.

  3. Every 10 minutes, ClickRuntime checks that email thread for a reply.

  4. When the approver replies "approve", the draft is published and they get a confirmation with the live link.

Before it runs live

  • Connect Google through your own Google app (a one-time, 10-minute setup), so it works with your own Gmail
  • Connect WordPress
  • Paste your automation's link into the other app's webhook settings

What you get

RunsThe moment it happens
Turn a document into a blog post you approve by emailjust nowSucceeded
Email · Approve postApprove post: How Clean Water Reached 3,000 Families in Northwind Valley. Reply 'approve' to publish.

Build your own

Need it to work differently?

This template is a starting point. Copy the prompt and change it, or describe a different automation from scratch, with your own conditions, more apps or an AI step. Your assistant writes it, tests it and runs it on ClickRuntime.
  • Your own rules

    Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.

  • Any number of apps

    One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.

  • AI where it helps

    Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.

  • On a schedule or on each event

    Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.

Changes you can ask for

  • Act only on the items that match your own rules, and skip the rest
  • Change what the AI looks for, or how it writes the result
  • Add another app, for example also send it to Slack
  • Combine it with other Gmail and WordPress steps into one automation

Under the hood

The code that runs this automation

This is the Python script that runs each time the automation starts. Your AI assistant writes it for you when you send the prompt, and you allow each step in your assistant. To change how the automation works, describe the change to your assistant and it updates the script for you. For every function it can use, see the script reference.
wordpress_post_from_a_document_approved_by_email.pyexample
import base64, io
from email.mime.text import MIMEText
from pypdf import PdfReader
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from clickruntime import on_event, on_trigger, credentials, http, state, ai

APPROVER = "director@example.org"
SCHEMA = {"type": "object", "properties": {k: {"type": "string"} for k in ["title", "excerpt", "body_html"]}, "required": ["title", "excerpt", "body_html"]}
WP = "https://blog.example.com/wp-json/wp/v2"

def wp(method, path, **kw):
    r = http.request(method, f"{WP}/{path}", auth=(credentials.secret("WP_USER"), credentials.secret("WP_APP_PASSWORD")), **kw)
    r.raise_for_status()
    return r.json()
def send_email(to, subject, text, thread_id=None, reply_to=None):
    mime = MIMEText(text)
    mime["to"], mime["subject"] = to, subject
    if reply_to:
        mime["In-Reply-To"] = reply_to
    body = {"raw": base64.urlsafe_b64encode(mime.as_bytes()).decode(), **({"threadId": thread_id} if thread_id else {})}
    return build("gmail", "v1", credentials=Credentials(credentials.connection("google", "work")), cache_discovery=False).users().messages().send(userId="me", body=body).execute()

@on_event
def handle(event):
    text = " ".join(p.extract_text() or "" for p in PdfReader(io.BytesIO(event.body.encode("latin-1"))).pages)[:20000]
    art = ai.generate(f"Turn this report into a 900-word blog post for supporters (HTML body):\n{text}", json_schema=SCHEMA, max_output_tokens=2048).json
    post = wp("POST", "posts", json={"title": art["title"], "excerpt": art["excerpt"], "content": art["body_html"], "status": "draft"})
    sent = send_email(APPROVER, f"Approve post: {art['title']}", f"Preview: {post['link']}&preview=true\n\nReply 'approve' to publish.")
    state.set("waiting", (state.get("waiting") or []) + [{"thread": sent["threadId"], "post": post["id"]}])
    return {"draft": post["id"]}

@on_trigger
def check_replies(event):
    gmail, waiting = build("gmail", "v1", credentials=Credentials(credentials.connection("google", "work")), cache_discovery=False).users(), state.get("waiting") or []
    for w in list(waiting):
        msgs = gmail.threads().get(userId="me", id=w["thread"], format="full").execute()["messages"][1:]
        if any(m.get("snippet", "").lower().startswith("approve") for m in msgs):
            link = wp("POST", f"posts/{w['post']}", json={"status": "publish"})["link"]
            send_email(APPROVER, "Published", link, thread_id=w["thread"])
            waiting.remove(w)
    state.set("waiting", waiting)
    return {"waiting": len(waiting)}

FAQ

Common questions

How do I send the PDF?
Send it to the automation's trigger link from a form, a shared drive action or a script. The PDF arrives as the body of the request.
What counts as approval?
A reply in the same email thread that starts with the word "approve". Other replies are ignored, so you can discuss changes in the thread first.
How quickly is it published after I reply?
Within about ten minutes, since replies are checked on that schedule.
What permissions does it need?
WordPress write; Gmail gmail.send + gmail.readonly. Nothing else in your accounts is used.
Does it need AI?
Yes. It uses ClickRuntime's built-in AI, so you don't need an OpenAI or Anthropic key. Every plan includes a monthly AI allowance.
How many runs does it use?
One run for each event the app sends.
Can I change how it works?
Yes. Describe the change to your AI assistant, for example a different schedule, channel or filter. It updates the automation, tests it and tells you what changed.

Set up “Turn a document into a blog post you approve by email” from your assistant

Copy the prompt above, or connect your assistant first. Free plan, no credit card.