Keyword Extractor
Extracts likely keywords from title, description, and body using stop-word filtering.
Function signature
ogExtractContentKeywords(content_fields, options = array())
Categories
- Search and Discovery
Parameters
content_fieldsAssociative content fields such as title, description, and body.optionsOptional stop_words, max_keywords, and min_length settings. Recognized keys: `max_keywords`, `min_length`, `stop_words`.Return value
Short public-safe status message.
- keywords
- counts
Compatibility
Existing function name and call order preserved; metadata signature corrected to source.
Minimum PHP version: 7.4
Security notes
Validate request method, identity, permissions, and caller-owned allowlists before use; keep secrets and internal paths out of public output.
Code
<?php
/*
* Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
* Free for personal and internal use. Paid project use requires visible credit
* to Jeffery L. Paris. Corporate use requires a paid license fee unless a
* separate written license states otherwise.
*/
/**
* Extracts likely content keywords using simple token frequency scoring.
*
* This is an editorial helper, not a machine-learning classifier. It strips
* tags, removes common stop words, and returns the strongest remaining terms.
*
* @param array $content_fields Associative content fields such as title, description, and body.
* @param array $options Optional stop_words, max_keywords, and min_length settings.
* @return array Structured result with keyword list and token counts.
*/
function ogExtractContentKeywords($content_fields, $options = array()) {
$result = array(
'success' => false,
'message' => '',
'data' => array()
);
if (!is_array($content_fields)) {
$result['message'] = 'Content fields must be an array.';
return $result;
}
if (!is_array($options)) {
$options = array();
}
$max_keywords = 12;
if (!empty($options['max_keywords'])) {
$max_keywords = (int)$options['max_keywords'];
}
if ($max_keywords < 1) {
$max_keywords = 12;
}
$min_length = 3;
if (!empty($options['min_length'])) {
$min_length = (int)$options['min_length'];
}
$stop_words = array('the', 'and', 'for', 'with', 'that', 'this', 'from', 'into', 'your', 'you', 'are', 'was', 'were', 'have', 'has', 'php');
if (!empty($options['stop_words']) && is_array($options['stop_words'])) {
$stop_words = array_merge($stop_words, $options['stop_words']);
}
$text = '';
foreach ($content_fields as $field_value) {
if (is_scalar($field_value)) {
$text .= ' ' . strip_tags((string)$field_value);
}
}
$text = strtolower(html_entity_decode($text, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'));
$tokens = preg_split('/[^a-z0-9]+/i', $text);
$counts = array();
foreach ($tokens as $token) {
$token = trim($token);
if (strlen($token) < $min_length) {
continue;
}
if (in_array($token, $stop_words, true)) {
continue;
}
if (!array_key_exists($token, $counts)) {
$counts[$token] = 0;
}
$counts[$token]++;
}
arsort($counts);
$keywords = array_slice(array_keys($counts), 0, $max_keywords);
$result['success'] = true;
$result['message'] = 'Content keywords extracted.';
$result['data'] = array(
'keywords' => $keywords,
'counts' => array_slice($counts, 0, $max_keywords, true)
);
return $result;
}