# 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.