Blog

Three Common Mistakes When Implementing RAG in WordPress

You launch an assistant based on the 2,000 articles on your site, and the first real question fails: the bot can’t find a guide published two years ago. The culprit is rarely the model; the technique has been validated since Meta’s 2020 paper, and failures usually occur where the pipeline touches WordPress. These are the three most common mistakes when setting up RAG in WordPress, each with its specific fix.

Error 1: chunking content exactly as the database returns it

Poor content chunking is the easiest mistake to make when building RAG in WordPress. The typical pipeline reads the wp_posts table and sends each complete entry to the embedding model; post_content accumulates block editor HTML, unresolved shortcodes, and markup inserted by other plugins into the content itself. The resulting vector is a fuzzy average, and retrieval fails precisely on specific questions.

Standard practice divides the text into fragments of 400 to 800 tokens with a 10-15% overlap. Use h2 and h3 headings as natural boundaries and apply the the_content filter before chunking so that shortcodes are converted into actual text. A cleaner like BeautifulSoup (in Python) removes residual markup. Each chunk must be readable on its own.

With clean chunks, the next decision is where those vectors live.

Error 2: storing the vectors in the WordPress database itself

A model like OpenAI’s text-embedding-3-small generates vectors with 1,536 dimensions. Storing them serialized in wp_postmeta and calculating similarities via PHP forces a full scan on every query, and response time grows as the number of entries increases. MySQL does not offer nearest neighbor indexes for this use case, and MariaDB did not incorporate vector search until version 11.6, released in late 2024; most WordPress hosting providers are still on earlier versions.

The correction is to separate the storage: Qdrant and Weaviate run in their own container, Pinecone works as a managed service, and pgvector adds approximate search to PostgreSQL in a single afternoon. If you need exact term matching in addition to semantic similarity, keep the MySQL FULLTEXT index and combine both results via hybrid search.

Separating the storage solves performance, but leaves another failure point open: what content each user can see.

Error 3: indexing without respecting WordPress permissions

A direct query like SELECT * FROM wp_posts WHERE post_type IN (‘post’, ‘page’) also collects drafts, content pending review, and private entries. If that material enters the index, any anonymous visitor can ask the chatbot for information reserved for registered users. Password-protected content follows the same path.

The correction has two layers. During ingestion, filter by post_status = ‘publish’ and store the post ID in the metadata of each vector. During the query, retrieve the candidates from the store and re-check permissions using current_user_can() or get_post_status() before returning text to the user; a private entry will thus appear only to those who are authorized to see it.

Conclusion: audit the pipeline before scaling

These three points impact any RAG project in WordPress with live content, and there is a silent fourth one that exacerbates them: a static index. Hook into save_post to regenerate the embedding of each entry when it changes and delete vectors from deleted content. Then, create a test bank with 20 real user questions and the URL that should answer each one; run it after every system change. And if you want an immediate win, open the query that feeds your ingestion today: if it doesn’t filter by post_status = ‘publish’, you already have an error to fix and a good reason to review the other two.

For the full setup, check the Ollama connection guide and the cost comparison.

Try it in 3 minutes

Install Ollama + Open WebUI on your computer, free and private.