What does the RankMeFirst publishing connection do?
RankMeFirst can send completed Content Planner articles to WordPress, Shopify, a GitHub-backed Decap CMS website, or a custom webhook. You choose whether each article is delivered as a draft, published automatically, or held for manual publishing.
The publishing connection does not give RankMeFirst access to your main website password. WordPress uses a revocable Application Password, Shopify uses credentials from a store-owned custom app, Decap uses a repository-limited GitHub token, and webhooks use a unique signing secret.
Before connecting a live website, use draft publishing and send one complete article. Check its title, formatting, links, image, author, category and URL before enabling automatic live publishing.
Which publishing behaviour should you choose?
RankMeFirst offers three publishing behaviours:
- Send to CMS as a draft automatically: The safest starting point. Generated articles are sent automatically but require review before publication.
- Publish live automatically: The article becomes public after its text and, when selected, its generated image are ready.
- Publish manually: Nothing is sent automatically. Open an individual generated article in RankMeFirst when you are ready to publish it.
The Wait for the generated image option delays delivery until the image is ready. Turn it off only if your CMS or editorial team adds images separately.
Only one publishing destination can be active for a business. Connecting a different destination replaces the existing connection.
Connect RankMeFirst to WordPress
What you need
- A WordPress website using HTTPS.
- A WordPress user that can create posts and upload media. An Author, Editor or Administrator role normally has the required capabilities.
- WordPress 5.6 or newer, with the REST API and Application Passwords enabled.
Do not enter your normal WordPress login password. WordPress Application Passwords are separate, revocable credentials designed for integrations. WordPress explains how Application Passwords work.
Step 1: Create a WordPress Application Password
- Sign in to the WordPress administration area, normally at
https://yourwebsite.com/wp-admin. - Open Users, then Profile. If an administrator is creating it for another user, open Users, then All Users, then edit that user.
- Scroll to Application Passwords.
- Enter
RankMeFirstas the new application name. - Select Add New Application Password.
- Copy the generated password immediately. WordPress displays it only once.
Spaces shown inside the generated password are normal. You can paste the password exactly as WordPress displays it.
Step 2: Enter the WordPress connection in RankMeFirst
- Open the business in the RankMeFirst dashboard.
- Open Content Planner.
- Select Connect publishing, then choose WordPress.
- Enter the public website URL, such as
https://example.com. - Enter the WordPress username belonging to the user that created the Application Password.
- Paste the Application Password. Do not enter the account’s regular password.
- Select draft, live or manual publishing.
- Choose whether RankMeFirst should wait for the article image.
- Select Connect and test.
RankMeFirst tests the WordPress REST API before saving the connection. A successful connection appears at the top of Content Planner as WordPress publishing.
Step 3: Test an article
Use draft publishing for the first article. In WordPress, open Posts, then All Posts, and locate the new draft. Check:
- The title and slug.
- Heading and paragraph formatting.
- Internal and external links.
- The featured image and image alt text.
- The author and publication status.
After the draft looks correct, publish it from WordPress or change the RankMeFirst connection to live publishing.
Common WordPress connection problems
WordPress rejected the username or Application Password: Confirm that the username and Application Password belong to the same user. Create a new Application Password instead of using the normal login password.
Application Passwords is missing: Confirm the site uses HTTPS and WordPress 5.6 or newer. A security plugin, hosting policy or custom code may have disabled Application Passwords.
The connection works but an article cannot upload its image: The connected user needs the upload_files capability. Use an Author, Editor or Administrator account, or ask the site administrator to adjust the role.
The REST API is blocked: Open https://yourwebsite.com/wp-json/wp/v2 in a browser. A security plugin, firewall or maintenance mode may be blocking authenticated REST requests.
Connect RankMeFirst to Shopify
What you need
- Shopify store-owner access, or a staff account allowed to create and install apps.
- The store’s permanent
myshopify.comdomain. - At least one Shopify blog, such as News.
You create the publishing app inside your own Shopify organization. This is a connector for your RankMeFirst account, not an app that you find or purchase in the Shopify App Store. RankMeFirst never receives your Shopify login password.
The app is limited to the write_content scope used to find blogs and publish blog posts. Shopify write scopes include the corresponding read access, so a separate read_content scope is unnecessary. Its Client ID and Client Secret are encrypted in RankMeFirst. Shopify access tokens expire after about 24 hours, so RankMeFirst obtains a new short-lived token automatically when publishing requires one. Shopify documents the client credentials grant and its security requirements.
The custom app and store must appear in the same Shopify organization. If a developer or collaborator does not own the store organization, ask the store owner to complete the app creation and installation steps.
Step 1: Find the permanent Shopify domain
The connection requires the store’s permanent domain, not a public custom domain such as example.com.
- Sign in to Shopify Admin.
- Open Settings, then Domains.
- Find the domain ending in
.myshopify.com. - Copy only the store domain, for example
your-store.myshopify.com.
Do not use the public storefront domain, an Admin URL containing /store/, or a domain belonging to a different store.
Step 2: Create a custom app
Start from the Shopify store so Shopify opens the correct organization:
- In Shopify Admin, open Settings.
- Select Apps.
- Select Develop apps.
- Select Build apps in Dev Dashboard.
- In Shopify Dev Dashboard, select Apps, then Create app.
- Under Start from Dev Dashboard, name the app
RankMeFirst Content Publisher. - Select Create app. Do not use the Shopify CLI option.
This app belongs to your Shopify organization and is used only as the publishing connection for your store.
If you already see RankMeFirst Content Publisher with an active version, do not create another copy. Open the existing app, confirm the version has the settings below, and continue to installation.
Step 3: Configure the app version
Shopify will ask you to create or configure an app version. Use these values:
- Keep the app name as
RankMeFirst Content Publisher. - Set App URL to
https://shopify.dev/apps/default-app-home. - Turn off Embed app in Shopify admin. RankMeFirst does not display an embedded Shopify page.
- Leave Preferences URL blank.
- Leave Webhooks API version at Shopify’s current default.
- Under API access, select Select scopes, search for
content, and add onlywrite_content. - Leave Optional scopes blank.
- Leave Use legacy install flow turned off.
- Leave Allowed redirection URL(s) blank. This connector does not use an OAuth redirect.
- Save or create the version.
Shopify documents that a write scope includes read access to the same resource. Do not be concerned if Shopify later reports only write_content; that is the expected and sufficient permission. Do not add unrelated customer, order, product or payment scopes.
Step 4: Release and install the app
- Select Release for the configured version.
- Confirm the release. The version should now show as Active.
- Return to the app’s Overview page in Shopify Dev Dashboard.
- In the Installs card, select Install app.
- Choose the correct store and approve the installation in Shopify Admin.
- Return to the app’s Overview and confirm the Installs count is no longer zero.
Releasing a version only prepares it for installation. RankMeFirst cannot connect until the app is installed on the target store.
If the store does not appear, confirm that the app and store are in the same Shopify organization and that your account is allowed to install apps.
Step 5: Copy the Client ID and Client Secret
- Return to the app in Shopify Dev Dashboard. Do not use the general Settings page inside the store Admin.
- Open App settings in the app’s left sidebar.
- Find Client credentials.
- Copy the Client ID.
- Reveal and copy the Client Secret.
Treat the Client Secret like a password. Do not send it by email, place it in website code or commit it to GitHub. RankMeFirst encrypts it after you submit the connection and never returns it to the browser.
Step 6: Connect and verify Shopify in RankMeFirst
- Open the business in RankMeFirst and go to Content Planner.
- Select Connect publishing, then choose Shopify.
- Enter the permanent
myshopify.comdomain. - Paste the app’s Client ID and Client Secret.
- Choose draft, live or manual publishing.
- Choose whether RankMeFirst should wait for the generated image.
- Select Connect and verify Shopify.
RankMeFirst requests a short-lived token and checks the store name, content permissions and available blogs. A successful test saves the encrypted connection. There is no Shopify popup in this flow.
Step 7: Choose the Shopify blog and author
- Select the blog that should receive generated articles.
- Enter the author name that should appear on articles.
- Confirm the publishing behaviour.
- Select Save settings.
For the first test, select draft publishing. In Shopify Admin, open Online Store, then Blog posts, and inspect the delivered draft.
Common Shopify connection problems
Shopify says the store domain is invalid: Use the permanent domain ending in .myshopify.com. Do not use the storefront’s custom domain or include an Admin URL path.
Shopify rejected the Client ID or Client Secret: Copy both values again from App settings in Shopify Dev Dashboard, not from the store’s general Settings. Confirm that the app has been installed on this store and that its Installs count is no longer zero.
The app cannot access this store: The custom app and store must belong to the same Shopify organization. Ask the store owner to create and install the app from the organization that contains the store.
RankMeFirst says the content scope is missing: Add write_content, release the new app version and approve the updated access on the store before testing again. A separate read_content scope is not required because Shopify includes read access with write_content.
Opening the installed app shows a blank page or 404: This connector has no embedded Shopify interface. Turn off Embed app in Shopify admin and manage publishing from RankMeFirst Content Planner instead.
The person connecting cannot create or install the app: Sign in as the store owner or use a staff account with app-development and installation permission. Collaborator access may not be sufficient.
No destination blog appears: Create a blog in Shopify first. Shopify stores commonly have a default News blog, but it may have been renamed or removed.
The connection later stops working: Confirm that the custom app is still installed and its Client Secret has not been rotated. Open publishing settings and enter the current Client ID and Client Secret to reconnect it.
Connect RankMeFirst to Decap CMS
What the Decap connection supports
The current Decap connector supports websites whose content is stored in a GitHub repository. RankMeFirst writes the article as Markdown and uploads its image to the configured repository folder.
Draft mode creates a rankmefirst/article-slug branch and opens a pull request. Live mode commits directly to the production branch. If the production branch is protected, use draft mode and merge the pull request after review.
Decap CMS documents Git-backed content repositories and explains how its editorial workflow uses branches and pull requests.
Step 1: Confirm the Decap content structure
Your Decap config.yml should have a GitHub backend, production branch, content folder, media folder and public media path. For example:
backend:
name: github
repo: owner/website-repository
branch: main
publish_mode: editorial_workflow
media_folder: public/images/blog
public_folder: /images/blog
collections:
- name: blog
label: Blog
folder: src/content/blog
create: true
extension: md
The current RankMeFirst connector writes this frontmatter:
title: "Article title"
description: "Article description"
publishDate: 2026-08-29
author: "Author name"
category: "Category"
readTime: "8 min read"
featured: false
Your website’s content schema must accept these field names and value types. If it requires different frontmatter fields, use the custom webhook connector until configurable Decap field mapping is available.
Step 2: Create a fine-grained GitHub token
- Sign in to the GitHub account that can write to the website repository.
- Open Settings, then Developer settings.
- Open Personal access tokens, then Fine-grained tokens.
- Select Generate new token.
- Name it
RankMeFirst publishing. - Choose an appropriate expiration date. A shorter expiration is safer but requires periodic reconnection.
- Choose the repository owner as the resource owner.
- Under repository access, choose Only select repositories and select the website repository.
- Under repository permissions, set Contents to Read and write.
- Set Pull requests to Read and write.
- Generate the token and copy it immediately. GitHub displays it only once.
GitHub documents the permissions used by fine-grained personal access tokens.
Step 3: Enter the Decap connection
- Open Content Planner, then Connect publishing.
- Choose Decap CMS.
- Enter the GitHub repository URL, for example
https://github.com/owner/website-repository. - Paste the fine-grained GitHub token.
- Enter the production branch, normally
main. - Enter the Decap content folder, such as
src/content/blog. - Enter the repository media folder, such as
public/images/blog. - Enter the public media path, such as
/images/blog. - Choose the default article category and author.
- Enter the public website URL. RankMeFirst uses it to link to a successfully published article.
- Choose draft, live or manual publishing.
- Select Connect and test Decap.
Step 4: Test a Decap draft
- Keep the connection in draft mode.
- Publish one completed article from RankMeFirst.
- Open the website repository on GitHub.
- Open Pull requests and select the RankMeFirst article pull request.
- Review the Markdown file, frontmatter and image.
- Use the site’s preview deployment if one is configured.
- Merge the pull request only after the preview is correct.
Common Decap connection problems
GitHub rejected the token: Confirm that the token has not expired, belongs to an account with repository access, and is restricted to the correct repository.
Contents or Pull requests permission is missing: Edit or replace the token with both repository permissions set to Read and write.
Repository, branch or content path was not found: Check the repository URL, branch name and folder spelling. Paths are case-sensitive.
The article commits but the website build fails: Compare the generated frontmatter with the site’s content schema. Required fields and accepted category values must match.
Live publishing fails on a protected branch: Switch to draft publishing. Review and merge the pull request through the repository’s normal approval process.
Connect RankMeFirst to a custom webhook
Use a webhook when your website has a custom CMS, a proprietary publishing API, or a content workflow not covered by the built-in connectors. A developer must create a public HTTPS endpoint that receives and stores the article.
Webhook requirements
The endpoint must:
- Use HTTPS and be reachable from the public internet.
- Accept an HTTP
POSTrequest with a JSON body. - Return a successful
2xxresponse within 20 seconds. - Avoid redirects.
- Verify every RankMeFirst signature before trusting the payload.
- handle both
connection.testandarticle.readyevents.
Localhost, private network addresses and endpoints that redirect are rejected for security.
Step 1: Save the endpoint and signing secret
- Open Content Planner, then Connect publishing.
- Choose Webhook.
- Enter the full HTTPS endpoint URL.
- Choose the publishing behaviour and image setting.
- Select Save webhook.
- Copy the signing secret immediately and store it in the receiving application’s secret manager. RankMeFirst does not display it again.
Step 2: Verify the signature
RankMeFirst sends these headers:
X-RankMeFirst-EventX-RankMeFirst-DeliveryX-RankMeFirst-TimestampX-RankMeFirst-Signature
The signature has the format sha256=HEX_DIGEST. Calculate the expected digest with:
HMAC_SHA256(signing_secret, timestamp + "." + raw_request_body)
Use the raw body bytes before parsing JSON. Compare signatures with a timing-safe function, reject timestamps older than five minutes, and store delivery IDs temporarily to prevent replayed requests.
A simplified Node and Express example:
import express from "express";
import { createHmac, timingSafeEqual } from "node:crypto";
const app = express();
app.post(
"/api/rankmefirst/articles",
express.raw({ type: "application/json" }),
async (request, response) => {
const rawBody = request.body.toString("utf8");
const timestamp = request.header("x-rankmefirst-timestamp") || "";
const received = (request.header("x-rankmefirst-signature") || "")
.replace(/^sha256=/, "");
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
return response.status(401).json({ error: "Expired request" });
}
const expected = createHmac("sha256", process.env.RANKMEFIRST_WEBHOOK_SECRET)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
const valid =
received.length === expected.length &&
timingSafeEqual(Buffer.from(received), Buffer.from(expected));
if (!valid) {
return response.status(401).json({ error: "Invalid signature" });
}
const payload = JSON.parse(rawBody);
if (payload.event === "connection.test") {
return response.status(200).json({ received: true });
}
if (payload.event === "article.ready") {
const savedArticle = await saveArticleToYourCms(payload.data);
return response.status(200).json({
externalId: savedArticle.id,
externalUrl: savedArticle.url,
});
}
return response.status(400).json({ error: "Unsupported event" });
},
);
Step 3: Handle the connection test
After the endpoint is ready, select Test webhook in RankMeFirst. The endpoint receives:
{
"event": "connection.test",
"deliveryId": "unique-delivery-id",
"timestamp": "unix-timestamp",
"data": {
"message": "RankMeFirst publishing connection test"
}
}
Return a 2xx response after validating the signature. RankMeFirst marks the connection active only after the test succeeds.
Step 4: Handle an article event
Completed articles use the article.ready event. Its data object contains:
articleIdandpublicationIdpublishingMode, eitherdraftorlivetitle,slug,excerpt,htmlandmarkdowntargetSearchimage, containingurlandaltText, ornullqualityScorescheduledDate
The receiver may return externalId and externalUrl. RankMeFirst stores these values so the publication can link back to the article in the external CMS.
Common webhook problems
Webhook could not be reached: Confirm that the endpoint is public, uses HTTPS, does not redirect and allows requests from the internet.
Webhook returned HTTP 401: Verify that the receiving code signs the exact raw request body with timestamp.body. Do not re-serialize parsed JSON before calculating the HMAC.
Webhook returned HTTP 500: Check the receiver’s server logs. Return success only after the article has been accepted or safely queued.
The test works but articles do not appear: Confirm the receiver handles article.ready, respects publishingMode, and stores either the HTML or Markdown content.
How do you disconnect or change a publishing connection?
Open the business, go to Content Planner, and select Settings on the publishing card.
- Select Disconnect publishing to stop all future deliveries and remove the stored connection credentials.
- Select another connector to replace the current destination.
- For WordPress, also revoke the RankMeFirst Application Password in the WordPress user profile if it will no longer be used.
- For Decap, revoke the GitHub token when the connection is no longer required.
- For Shopify, uninstall the custom app from the store and delete it from Shopify Dev Dashboard when it is no longer required.
- For a webhook, delete the old signing secret from the receiving service.
Disconnecting publishing does not delete articles that were already delivered to the website. Those articles must be removed from the destination CMS separately.
What should you test before enabling live publishing?
Use this checklist with one draft article:
- Confirm the correct website and destination blog are connected.
- Check the article title, slug and meta description.
- Review headings, lists, tables and links.
- Confirm the image loads and its alt text is useful.
- Check the author, category and publication date.
- Open the article preview on desktop and mobile.
- Confirm the CMS can update or remove the article normally.
- Publish the draft manually.
- Enable live publishing only if the complete workflow behaved as expected.
If a connection test fails, keep manual or draft publishing enabled while investigating. A failed publishing delivery never needs to become a failed article generation.
See Your GEO Score in 60 Seconds
Find out exactly where your business stands on AI search — free, no credit card needed.
Get My Free GEO Audit