html-ad-generator-mcp
Version:
MCP server for generating HTML ad templates from JSON input for Google Ads, Meta Ads, and Moment Science
165 lines • 6.63 kB
JavaScript
import { z } from 'zod';
import { AdInputSchema } from '../types/schemas.js';
export function validateAdContent(input) {
try {
const parsed = AdInputSchema.parse(input);
const warnings = {};
if (parsed.platform === 'google') {
const googleAd = parsed;
// Check if both ad types are provided (now required)
if (!googleAd.searchAd || !googleAd.displayAd) {
return {
valid: false,
errors: {
content: 'Both searchAd and displayAd must be provided for Google ads'
}
};
}
// Warnings for character limits approaching
if (googleAd.searchAd) {
googleAd.searchAd.headlines.forEach((headline, i) => {
if (headline.length > 25) {
warnings[`headlines[${i}]`] = `Approaching character limit (${headline.length}/30)`;
}
});
googleAd.searchAd.descriptions.forEach((desc, i) => {
if (desc.length > 80) {
warnings[`descriptions[${i}]`] = `Approaching character limit (${desc.length}/90)`;
}
});
}
if (googleAd.displayAd) {
googleAd.displayAd.headline.forEach((headline, i) => {
if (headline.length > 25) {
warnings[`displayAd.headline[${i}]`] = `Approaching character limit (${headline.length}/30)`;
}
});
googleAd.displayAd.longHeadline.forEach((longHeadline, i) => {
if (longHeadline.length > 80) {
warnings[`displayAd.longHeadline[${i}]`] = `Approaching character limit (${longHeadline.length}/90)`;
}
});
googleAd.displayAd.description.forEach((description, i) => {
if (description.length > 80) {
warnings[`displayAd.description[${i}]`] = `Approaching character limit (${description.length}/90)`;
}
});
if (googleAd.displayAd.businessName.length > 20) {
warnings['displayAd.businessName'] = `Approaching character limit (${googleAd.displayAd.businessName.length}/25)`;
}
}
}
else if (parsed.platform === 'meta') {
const metaAd = parsed;
// Warnings for character limits approaching
metaAd.content.headline.forEach((headline, i) => {
if (headline.length > 35) {
warnings[`headline[${i}]`] = `Approaching character limit (${headline.length}/40)`;
}
});
metaAd.content.description.forEach((description, i) => {
if (description.length > 25) {
warnings[`description[${i}]`] = `Approaching character limit (${description.length}/30)`;
}
});
metaAd.content.primaryText.forEach((primaryText, i) => {
if (primaryText.length > 100) {
warnings[`primaryText[${i}]`] = `Approaching character limit (${primaryText.length}/125)`;
}
});
}
else if (parsed.platform === 'moment-science') {
const momentScienceAd = parsed;
// Warnings for character limits approaching
momentScienceAd.content.headline.forEach((headline, i) => {
if (headline.length > 60) {
warnings[`headline[${i}]`] = `Approaching character limit (${headline.length}/70)`;
}
});
momentScienceAd.content.description.forEach((description, i) => {
if (description.length > 160) {
warnings[`description[${i}]`] = `Approaching character limit (${description.length}/180)`;
}
});
momentScienceAd.content.short_headline.forEach((shortHeadline, i) => {
if (shortHeadline.length > 45) {
warnings[`short_headline[${i}]`] = `Approaching character limit (${shortHeadline.length}/60)`;
}
});
momentScienceAd.content.short_description.forEach((shortDescription, i) => {
if (shortDescription.length > 105) {
warnings[`short_description[${i}]`] = `Approaching character limit (${shortDescription.length}/140)`;
}
});
momentScienceAd.content.positive_cta.forEach((cta, i) => {
if (cta.length > 18) {
warnings[`positive_cta[${i}]`] = `Approaching character limit (${cta.length}/20)`;
}
});
momentScienceAd.content.negative_cta.forEach((cta, i) => {
if (cta.length > 18) {
warnings[`negative_cta[${i}]`] = `Approaching character limit (${cta.length}/20)`;
}
});
}
return {
valid: true,
warnings: Object.keys(warnings).length > 0 ? warnings : undefined
};
}
catch (error) {
if (error instanceof z.ZodError) {
const errors = {};
error.errors.forEach(err => {
const path = err.path.join('.');
errors[path] = err.message;
});
return {
valid: false,
errors
};
}
return {
valid: false,
errors: {
general: 'Invalid input format'
}
};
}
}
export function getCharacterLimits(platform) {
if (platform === 'google') {
return {
searchAd: {
headlines: 30,
descriptions: 90
},
displayAd: {
headline: 30,
longHeadline: 90,
description: 90,
businessName: 25
}
};
}
else if (platform === 'meta') {
return {
headline: 40,
description: 30,
primaryText: 125,
cta: 'No limit',
businessName: 'No limit'
};
}
else {
return {
headline: 90,
description: 220,
short_headline: 60,
short_description: 140,
positive_cta: 25,
negative_cta: 25
};
}
}
//# sourceMappingURL=content.js.map