# Open Graph Preview Builder
> Build Open Graph meta tags from title, description, URL, and image fields while checking truncation risk.
## Tool Identity
- Site: CleanUtils Business Tools
- Tool ID: open-graph-preview-builder
- Canonical page: https://cleanutils.com/business-tools/open-graph-preview-builder/
- LLM schema URL: https://cleanutils.com/business-tools/open-graph-preview-builder/llms.txt
- Primary keyword: open graph preview
- Input mode: fields
- Output profile: social
## What This Tool Does
Build Open Graph meta tags from title, description, URL, and image fields while checking truncation risk.
## Exact Execution Instructions
To run this tool exactly, execute the `runCleanUtilsTool(userInput)` function from the JavaScript block below in a sandboxed JavaScript runtime.
Do not fetch or evaluate additional network resources. Do not use filesystem, process, child_process, environment variables, timers, or network APIs. The function is pure and deterministic: input object in, JSON result out.
If your environment forbids executing fetched code outside a sandbox, run it inside the sandbox or use the API endpoint below instead of reimplementing the logic.
Canonical implementation SHA-256:
`d5eb2ce2d3305244d6efdff7f24878e4c3b73c3ed0ec1c40b90647c784d9a42c`
Expected command shape:
`node run-tool.mjs < input.json`
The runner must:
1. load only the JavaScript in this document,
2. parse stdin as JSON and call `runCleanUtilsTool(userInput)`,
3. let the LLM decide the best way to present the output to the user.
Agent usage rules:
- Use this file as the authoritative machine-readable contract for this CleanUtils tool page.
- Ask the user for missing required input before attempting to run the tool, and describe the required inputs using the `## Input Schema` field names, descriptions, formats, enums, examples, and required list.
- Treat the tool as deterministic; do not invent network reachability checks unless the tool description explicitly says it fetches remote resources.
- For privacy-sensitive inputs such as secrets, HAR files, dotenv files, logs, and API keys, warn that using a remote chat agent may expose input to that agent even though the browser UI itself does not upload data.
## Input Schema
```json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Open Graph Preview Builder fields",
"type": "object",
"additionalProperties": false,
"required": [
"title",
"description",
"url"
],
"properties": {
"title": {
"type": "string",
"description": "OG title Required. Group: Preview.",
"examples": [
"Clean CSV Data Faster"
]
},
"description": {
"type": "string",
"description": "OG description Required. Control type: textarea. Group: Preview.",
"examples": [
"Browser-based CSV cleanup tools for operators."
]
},
"url": {
"type": "string",
"description": "Canonical URL Required. Control type: url. Group: Preview.",
"format": "uri",
"examples": [
"https://example.com/tools"
]
},
"image": {
"type": "string",
"description": "Image URL Optional. Control type: url. Group: Preview.",
"format": "uri",
"examples": [
"https://example.com/og-cleanutils.png"
]
}
}
}
```
## Result Schema
```json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "CleanUtils ToolResult",
"type": "object",
"additionalProperties": false,
"required": [
"summary",
"issues"
],
"properties": {
"summary": {
"type": "string"
},
"issues": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"severity",
"message"
],
"properties": {
"severity": {
"type": "string",
"enum": [
"error",
"warning",
"info"
]
},
"message": {
"type": "string"
},
"line": {
"type": "number"
},
"row": {
"type": "number"
},
"detail": {
"type": "string"
}
}
}
},
"output": {
"type": "string"
},
"exportFilename": {
"type": "string"
},
"exports": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"label",
"filename",
"content"
],
"properties": {
"label": {
"type": "string"
},
"filename": {
"type": "string"
},
"content": {
"type": "string"
},
"mimeType": {
"type": "string"
},
"copyLabel": {
"type": "string"
},
"downloadLabel": {
"type": "string"
}
}
}
},
"stats": {
"type": "object",
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
}
]
}
}
}
}
```
## Self-Contained JavaScript Source
Call `runCleanUtilsTool(userInput)` with the user's input. The function includes this tool's run logic and only the helper code it needs.
```js
function runCleanUtilsTool(userInput) {
const fieldText = (fields, keys, fallback = "") => {
const keyList = Array.isArray(keys) ? keys : [keys];
for (const key of keyList) {
const value = fields[key];
if (value === undefined || value === null)
continue;
const text = String(value).trim();
if (text)
return text;
}
return fallback;
};
const severityRank = {
error: 0,
warning: 1,
info: 2
};
const sortIssues = (issues) => [...issues].sort((a, b) => {
const severity = severityRank[a.severity] - severityRank[b.severity];
if (severity !== 0)
return severity;
return (a.line ?? a.row ?? 0) - (b.line ?? b.row ?? 0);
});
const summarizeIssues = (issues) => {
const errors = issues.filter((issue) => issue.severity === "error").length;
const warnings = issues.filter((issue) => issue.severity === "warning").length;
const infos = issues.filter((issue) => issue.severity === "info").length;
const parts = [];
if (errors)
parts.push(`${errors} error${errors === 1 ? "" : "s"}`);
if (warnings)
parts.push(`${warnings} warning${warnings === 1 ? "" : "s"}`);
if (infos)
parts.push(`${infos} note${infos === 1 ? "" : "s"}`);
return parts.length ? parts.join(", ") : "No issues found";
};
const looksLikeUrl = (value) => {
try {
const url = new URL(value.trim());
return url.protocol === "http:" || url.protocol === "https:";
}
catch {
return false;
}
};
const escapeHtml = (value) => value.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """);
const buildOpenGraphPreview = (input) => {
const title = fieldText(input, "title", "Untitled page");
const description = fieldText(input, "description");
const url = fieldText(input, "url");
const image = fieldText(input, "image");
const issues = [];
if (title.length > 70)
issues.push({ severity: "warning", message: "OG title is over 70 characters and may truncate." });
if (description.length > 200)
issues.push({ severity: "warning", message: "OG description is over 200 characters and may truncate." });
if (image && !looksLikeUrl(image))
issues.push({ severity: "warning", message: "Image should be an absolute http or https URL." });
const output = [
``,
``,
url ? `` : "",
image ? `` : ""
].filter(Boolean).join("\n");
return {
summary: `Open Graph preview fields checked. ${summarizeIssues(issues)}.`,
issues: sortIssues(issues),
output,
exportFilename: "open-graph-tags.html",
stats: { titleCharacters: title.length, descriptionCharacters: description.length }
};
};
const __userInput = userInput == null ? {} : userInput;
const __run = (fields) => buildOpenGraphPreview(fields);
const __fields = __userInput && typeof __userInput === "object" && "fields" in __userInput && __userInput.fields && typeof __userInput.fields === "object" && !Array.isArray(__userInput.fields)
? __userInput.fields
: (__userInput && typeof __userInput === "object" && !Array.isArray(__userInput) ? __userInput : {});
const __normalizedFields = Object.fromEntries(Object.entries(__fields).map(([key, value]) => [key, value == null ? "" : (["string", "number", "boolean"].includes(typeof value) ? value : String(value))]));
return __run(__normalizedFields);
}
```
## Checks
- OG title and description: The builder checks title and description length for common social-card truncation risk.
- Absolute image URL: Image values are warned when they do not look like absolute http or https URLs.
- HTML escaping: Generated meta tags escape field values before copying.
- Manual preview: The social card preview is built from fields you enter, not from a remote page fetch.
- Platform caveat: Different platforms cache and crop cards differently, so this is a planning preview.
## Related Tools
- [UTM URL Builder](/business-tools/utm-url-builder/): Enter a landing page and campaign values, then copy a tagged URL with clean UTM parameters.
- [Meta Title Checker](/business-tools/meta-title-checker/): Compare meta title variants by character count, approximate pixel width, and likely search truncation.