Cómo creé una web automática con +930 clics en < 3 meses

crear una web automática

Última actualización:

No te voy a vender una web en 5 minutos ni una moto a euro y medio. La automatización también lleva su tiempo y costes, aunque permite acelerar procesos y que un único profesional abarque mucho más trabajo. De hecho, te voy a mostrar cómo he creado una web automática en WordPress yo solito.

Tabla de contenidos

Pequeña reflexión acerca del futuro laboral y la IA

Desde hace muchos años, la especialidad profesional ha sido un tema de preocupación frecuente para los grandes pensadores de la sociedad. Incluso los teóricos sociológicos clásicos hablaban sobre el peligro que corría la especialización profesional.

Dicho de un modo rápido, pensaban que la especialización provocaría que desconociéramos lo que existía fuera de nuestro alcance profesional, y que algunas entidades como la burocracia, acabarían obteniendo vida propia y estando fuera de nuestro control. Entonces, los profesionales serían parte de un organismo que no comprenderían en su totalidad.

Podemos decir que, a día de hoy, el paradigma ha cambiado. La IA está evolucionando de un modo inabarcable, ha llegado incluso a sorprender a Google y otras grandes empresas del mundo digital. Además, están naciendo nuevos perfiles profesionales que abarcan un conocimiento más horizontal.

Últimamente se habla mucho del perfil profesional tipo T, el cual cuenta con una especialidad y un amplio conocimiento de todo lo que rodea su materia principal. Un tipo de profesional al que le veo un gran futuro. De hecho, este artículo es perfecto para este tipo de profesionales, si sigues leyendo descubrirás por qué.

Valores de rendimiento de esta web

Aunque desde mi punto de vista no son el factor determinante para el éxito de un proyecto web, vamos a empezar con los valores de rendimiento que sé que a muchos os gustan las gráficas bonitas y los números redondos.

Todos los valores que muestro a continuación son del día en que escribo este artículo (12/07/23) o del día anterior.

Pagespeed Insights

Los valores que encontramos en esta plataforma no están nada mal, 99 para la versión móvil y 100 para la versión escritorio. La verdad es que podría haberme puesto a optimizar aún más la carga de archivos, pero he dicho “para qué”, así podéis ver lo que se puede conseguir con un servidor de alto rendimiento como Wetopi y un tema que carga rápido.

Compara el TTFB de tu web con el de una copia en Wetopi.
Migramos una copia de tu web sin compromiso ni coste alguno.

Regístrate en 10 segundos y obtén tu cuenta con migraciones gratuitas de WordPress.

Hay que tener en cuenta que se han obtenido estos valores incluso usando herramientas que afectan de forma considerable al rendimiento, como Clarity de Microsoft, Google Analytics y Complianz.

Rendimiento 100 en PageSpeed Insights para ordenador
Resultados Page Speed Insights de la casi totalidad de páginas.
Resultado de 100 en PageSpeed Insights para móvil
Resultado Page Speed de Google, de una de las páginas con más impresiones.

Estos valores son los que lanza la página con más impresiones y visitas de la web. El resto de páginas no tienen un valor inferior, hay varias que incluso tienen 100/100.

Google Search Console

La verdad es que esta gráfica es bien bonita, desde el día en que se lanzó la web no ha parado de crecer progresivamente.

Según creo, aún le queda tiempo para pegar el estirón, ya que el 50% de las impresiones y clics se las están llevando tan solo 2 páginas, algunas de las 250 páginas iniciales se están empezando a posicionar en 1ª página ahora. Aún queda mucho recorrido.

evolución de las impresiones, clics y posición media en Google Search Console
Resultados sobre impresiones, CTR y posición, mostrados en Google Search Console

No he añadido el CTR medio para que sea más visual, pero los que estáis acostumbrados a ver estas gráficas supongo que os haréis una idea.

Microsoft Clarity

En Clarity he sacado una información bastante buena para estudiar la interacción de los usuarios. Pero como os quiero mostrar la miga, os enseño una captura del tiempo que suelen pasar los usuarios en esta web.

Estadísticas de Clarity sobre el tiempo que pasan los usuarios
Resultados audiencia desde Microsoft Clarity.

Web automática en WordPress y sin plugins

El uso de WordPress tiene un gran número de ventajas. Pero en este caso tendríamos que destacar la gran capacidad de personalización a la que podemos acceder.

Voy a meter las manos en la masa e intentar explicar del mejor modo posible cómo he creado esta web

Tecnologías usadas para este proyecto

  • Herramientas profesionales de marketing de contenidos para estudio de Kws y competencia
  • ChatGPT API
  • Google Sheets API
  • Leonardo.ai API
  • WordPress, Gutenberg
  • Código nativo de WordPress y PHP
  • REST API de WordPress
  • JavaScript (jQuery y jsPDF)
  • MySQL
  • HTML y CSS
  • Keyword combinator
  • Shuffle text lines
  • NAS
  • Bash
  • Python

Pasos al crear esta web automatizada en WordPress

He querido dedicarle mi tiempo a la planificación del proyecto. Los pasos han sido los siguientes:

  1. Estudio de Kws y competencia
  2. Planificación de pasos a seguir
  3. Preparación de archivo en Google Sheets
  4. Ensayo de prompts con la API de chatGPT
  5. Público objetivo
  6. Diseño de la web
  7. Creación de un tema en WordPress para la ocasión
  8. Crear el contenido principal de la web en WordPress con las API de chatGPT4, de Google Sheets y de Leonardo.ai
  9. Crear el resto del contenido
  10. Registro y membresía
  11. Últimos retoques
  12. Aplicación para crear artículos automáticos programados mediante un NAS y Python

Sobre el proyecto

Esta web automatizada trata sobre una temática que consideré muy apropiada para trabajar con chatGPT por varios motivos:

  • No existirán errores informativos provenientes de la IA
  • El contenido automático es 99% creativo
  • A través de una serie de implementaciones haremos que los usuarios fácilmente interaccionen con la web
  • La intención de búsqueda de los usuarios es muy clara
  • Podremos ofrecer un “Link Magnet” sencillo y que probablemente funcione bien
  • El nicho no está explotado por webs verticales
  • Se pueden crear 250 URLs (incluso más) sin miedo a encontrar errores

Aunque yo soy más de Lovecraft, este proyecto es muy Danielle Steel. Sí, ya lo sé, es un poco cursi, pero oye, si funciona funciona…

Por motivos evidentes no voy a facilitar el dominio de la web en cuestión, pero si queréis ir conociendo más detalles de este proyecto iré publicando en LinkedIn cómo va creciendo. Y cuando crea que está afincado en su temática lo haré público.

Además, aún quiero implementar varios métodos de monetización y no quiero que a cualquiera que vea la web se le encienda la bombilla.

Lo que sí puedo decir de esta web automática es que:

  1. Ofrece un contenido creativo bastante buscado en Google
  2. Este contenido se muestra en la web a modo de ejemplo
  3. Se da la capacidad de editar el contenido creativo
  4. Existe una caja para que los usuarios puedan crear contenido creativo nuevo mediante IA
  5. Existe un botón para enviar el contenido generado por WhatsApp
  6. Si los visitantes se registran se da la capacidad de descargar en PDF el contenido de ejemplo, creado y/o editado

Como podemos ver, la interacción del usuario es vital en este proyecto. Y creo que gracias a esto se están creando unos tiempos en las páginas bastante buenos. Por ejemplo, una página tiene en Junio un tiempo de interacción medio de 10’25” y ¡hay algunas visitas que superan los 40 minutos!.

Estudio de Kws y competencia

He utilizado varias herramientas profesionales para el estudio de palabras clave. La verdad es que no recuerdo cómo llegué a dar con la kw raíz de la que nació todo el proyecto. Supongo que estaría investigando a algún competidor de algún otro proyecto.

Pero cuando dí con ella me sorprendió el hecho de que no existiese ninguna web que le diese respuesta de manera vertical. Así que me descargué un archivo CSV con todas las palabras clave que esta herramienta me facilitó para trabajar una estructura de URLs interesante.

Planificación

Con el archivo CSV pude escoger las Kws más intereasantes y a las que les veía algo de futuro. Así que las resumí en 2 grupos, 1 categoría principal y una categoría secundaria. Es decir, todos estos artículos pertenecen a dos categorías.

Categoría principal

  • novio
  • novia
  • madre
  • padre
  • hermana
  • hermano
  • amigo
  • amiga
  • marido
  • mujer
  • hijo
  • hija

Categoría secundaria

  • para llorar
  • originales
  • con sentimiento
  • largas
  • cortas
  • para cumpleaños
  • para san valentin
  • para despedidas
  • ultimas
  • bonitas
  • inolvidables
  • romanticas
  • para la distancia
  • para aniversario
  • no cursis
  • virtuales
  • tristes
  • sinceras
  • para pedir perdon
  • con dolor
  • formales
  • poeticas
  • para echar de menos
  • para los buenos dias
  • de reconciliacion

Preparación de archivo en Google Sheets

La preparación de nuestro Google Sheets es de lo más importante en este proyecto, ya que contendrá la estructura de toda la web, así como los prompts más importantes del contenido automatizado.

Dividí el archivo en 10 columnas para alimentar los prompts:

  1. Rol
  2. Kw
  3. Kws secundarias
  4. Categoría principal
  5. Tono
  6. URL
  7. Categoría secundaria
  8. Cantidad de palabras
  9. Sustantivos
  10. Prompt

O sea, sin la columna del Prompt, quedaría algo así:

RolKwKws secundariashacia/cattonourlcategoríaspalabrasSustantivos
la novialloraremoción, cariño, amor, te quieronoviomelancólico y cariñosollorarpara hacer llorar800almohada,camisa,color
la noviate amoallí donde lleguemos, en mis sueños, he perdido la cordura, eres como el arroz chino y yo los palillosnoviooriginal, creativo,cariñoso y divertidooriginaloriginal900abeja,calle,charco
la noviami corazónentrañas, pasión, alegría, locuranoviosentimental, pasionalsentimientocon sentimiento800agua,bota,clima

Como ya os habréis imaginado, cada línea será una URL independiente.

Escribir 250 líneas con contenido único sería un trabajo de semanas. Así que siempre podremos encontrar herramientas de automatización para esto ¿Y cómo lo he hecho? Muy sencillo, he entrado a chatGPT (versión 3.5) y le he preguntado “Escribe un completo listado de tonos de escritura que chatGPT puede interpretar”.

Los resultados los he dividido en 3 y los he añadido a 3 columnas en Keyword combinator, una herramienta que permite crear cadenas de texto con el separador que creamos conveniente, en este caso la coma.

Luego he añadido el resultado en otra herramienta llamada Shuffle Text Lines, la que mezclará todas las líneas para darnos un resultado aleatorio. Y bueno, así tendremos todos los valores para la columna tono en menos de 10 minutejos.

Para la columna Kws secundarias he hecho lo mismo pero cambiando la pregunta en chatGPT. Esta sería: “Escríbeme un listado de 100 palabras que encajen con la palabra clave principal de este proyecto”.

Para añadir aún más autenticidad en cada artículo le he pedido a chatGPT que genere un chaparrón de sustantivos separados por comas. Y al igual que para las otras columnas he usado las herramientas Keyword combinator y Shuffle Text Lines.

Y por último el trabajo más aburrido, escoger Kw principal para cada artículo y revisar una a una cada línea para ver que todo encaja bien. Este trabajo manual sirve para verificar que toda la estructura de los prompts tiene sentido, ya que al colocar el tono y las palabras clave secundarias de forma aleatoria es muy probable que existan incongruencias.

He de decir que aunque añadí el campo de cantidad de palabras, chatGPT se lo pasó por el forro.

Ensayo de prompts con la API de chatGPT

Antes de empezar con el desarrollo he dedicado un buen tiempo exclusivamente a ver cómo la API de chatGPT respondía a los prompts para encontrar el que más se ajustaba a lo que quería.

Al querer que se publicase todo en Gutenberg de forma automática, no he encontrado forma de que chatGPT genere el contenido con las etiquetas HTML y los comentarios característicos de Gutenberg.

También, otro problema que encontré es que siempre devolvía el contenido HTML con las etiquetas <body> y <head>.

Estos problemillas los he tenido que solucionar en el procesado posterior mediante PHP.

Creación de un tema en WordPress para la ocasión

Además de que los servidores de Wetopi me sorprendieron en cuanto a velocidad, he querido ir un paso más allá y he creado un tema personalizado para este proyecto.

Para no romper tu web producción

los entornos de prueba “staging” son la solución.

Clona para tu Staging y hacer pruebas de forma segura

Clonar un sitio de WordPress con Wetopi es tan fácil como un simple clic.

Me he limitado a añadir los archivos imprescindibles, además de un par de page-templates, una carpeta con los archivos .js y otra con los archivos .css.

Los page-templates los uso para crear la estructura concreta de cada grupo de páginas/posts y para poner en cola los archivos .js y .css concretos de cada uno de ellos. Esto último lo hago mediante la función condicional is_page_template(). De esta forma podemos segmentar y quitar el CSS que no se use de cada página concreta de nuestro WordPress.

Público objetivo

No soy un experto en marketing, y definir el público objetivo es una tarea que siempre me ha costado bastante.

Aunque en este proyecto tenía una idea inicial relativamente clara en cuanto a los usuarios que accederán de forma orgánica, me di cuenta que había algunas búsquedas que se salían de ese perfil.

Por ejemplo, para las categorías novio con sentimiento, intuía que las búsquedas serían más de chicas y chicos de entre 14 y 25 años. Pero para categorías como hijo echar de menos, supongo que los usuarios y usuarias que hiciesen esas búsquedas serían madres y padres de entre 30 y 50 años.

Algo que tenía claro es que esta web iba a funcionar en sudamérica incluso mejor que en Europa. Y la verdad, por ahora parece que está siendo así.

Diseño de la web

Me he decidido a crear una pequeña membresía en la que se pide edad y mail para acceder a la posibilidad de descarga del PDF con el contenido de ejemplo, creado y/o editado. Así voy obteniendo los mails para una posible newsletter en el futuro.

Además, el diseño que en un principio he creado es muy sobrio, neutro, diría que incluso feucho. Una vez que tenga una cantidad de datos demográficos considerable cambiaré el diseño de la web. Y bueno, decir que tras 3 meses estando online, los datos revisados me han sorprendido bastante:

Rango de edad de los usuarios de la wev

Y yo pensaba que los visitantes tendrían entre 14 y 25 años… ¡Menos mal que no creé un diseño enfocado en este público!.

Los detalles gráficos de la web que no han sido generados mediante API externa, como el logo, los iconos de la home, etc. se han creado en SVG para una carga más rápida. Para permitir subir SVG a WordPress hay que configurar un par de cositas en código, ya que por defecto no se puede.

Crear el contenido principal de la web en WordPress con las API de chatGPT, Google Sheets y Leonardo.ai

Me voy a limitar a explicar “en prosa” cómo he desarrollado el plugin para generar el contenido automático, porque como me ponga en plan tutorial no dará tiempo a que nos comamos las uvas. Pero si os surge alguna duda estaré encantado de responderos a través de LinkedIn.

Hay que tener en cuenta que este plugin se ha creado para su uso en local, bajo un servidor Apache.

Este plugin consta de 3 archivos con las clases para cada API, recordemos que he usado las APIs de Google Sheets, chatGPT y Leonardo.ai. Cuenta con la siguiente estructura:

Estructura de archivos para las APIs de Google Sheets, ChatGPT y Leonardo.ai
  1. Sheets: Esta clase contiene un único método que realiza la conexión a la API y obtiene los valores del Google Sheet previamente configurado
  2. GPT: Esta clase contiene:
    • Método de conexión a la API
    • Método para generar la introducción
    • Método para generar el contenido creativo
    • Método para generar la metadescription
  3. LEO: En esta clase he añadido varios métodos:
    • Llamada para generación de imagen
    • Método de conexión
    • Llamada para obtención de URL de imagen según el ID obtenido en el método anterior
    • Método para subir imagen a WordPress desde una URL externa. Este método sí que me parece de lo más útil, así que os lo dejo por aquí:
public function up_img( $image_url, $new_name ) {
require_once( ABSPATH . 'wp-admin/includes/file.php' );

        ////Descargamos la imagen a una variable que contiene los datos temporales
        $temporal = download_url( $image_url );

        if( is_wp_error( $temporal ) ) {
            return false;
        }

        //Descargamos el archivo a la carpeta uploads
        $file = array(
            'name'     => basename( $new_name . '.jpg' ),
            'type'     => mime_content_type( $temporal ),
            'tmp_name' => $temporal,
            'size'     => filesize( $temporal ),
        );

        $sideload = wp_handle_sideload(

            $file,
            array(
                'test_form'   => false
            )
        );

        if( ! empty( $sideload[ 'error' ] ) ) {
            return false;
        }

        //Añadimos el archivo a la base de datos para que aparezca en la sección media del panel de control

        $attachment_id = wp_insert_attachment(

            array(
                'guid'           => $sideload[ 'url' ],
                'post_mime_type' => $sideload[ 'type' ],
                'post_title'     => basename( $sideload[ 'file' ] ),
                'post_content'   => '',
                'post_status'    => 'inherit',
            ),

            $sideload[ 'file' ]
        );

        if( is_wp_error( $attachment_id ) || ! $attachment_id ) {
            return false;
        }

        //Actualizamos metadatos
        require_once( ABSPATH . 'wp-admin/includes/image.php' );

        wp_update_attachment_metadata(
            $attachment_id,
            wp_generate_attachment_metadata( $attachment_id, $sideload[ 'file' ] )
        );

        return $attachment_id;
    }

Como habéis visto en la estructura, cuento también con dos archivos en la carpeta control y un archivo en la carpeta raíz.

El archivo raíz no contiene más que los archivos de configuración y activación que todo plugin tiene. Gracias a este archivo contaremos con una sección en el panel de control. Y aquí es donde entra el archivo de control acgpt_callback.php:

acgpt_calbback.php incluye un formulario con un simple botoncito que se mostrará en la sección del plugin del panel de control de WordPress. Este botón llamará a una función alojada en el archivo acgpt_form.php. En este último archivo es donde sucede la magia, y hace lo siguiente:

  1. Se llama a la API de Google Sheets y se obtienen las filas
  2. Se crea un bucle para tratar las filas 1 a 1
  3. Se obtienen los datos de categorías, rol, hacia y Kws y se crea la introducción con la API de chatGPT
  4. Se crea el contenido creativo con la API de chatGPT. Para esto se usan los datos del Sheet de rol, Kws, hacia, tono, categorías, prompt y sustantivos
  5. Se crea el contenido final con la API de chatGPT explicando por qué es importante crear ese contenido creativo
  6. Creamos también la metadescription con la API de chatGPT
  7. Creamos un prompt para la API de LEO teniendo en cuenta los campos rol, hacia y Kw y lo guardamos en una variable
  8. Generamos imagen con la API de LEO, obtenemos la URL según el ID y la subimos a WordPress
  9. Todo el contenido generado por chatGPT se filtra y se sustituyen las etiquetas HTML definidas en el prompt por las etiquetas con los comentarios de Gutenberg
  10. El paso 7 nos devuelve el ID de la imagen ya subida en nuestro WordPress. Es entonces cuando podremos crear el artículo en WordPress añadiendo todo el contenido generado:
$post_arr = array(
'post_title'   => $title,

    'post_content' => $final_article,
    'post_status'  => 'publish',
    'post_category' => array('6'),
    'meta_input'   => array(
        '_yoast_wpseo_focuskw'     => $main_kw,
        '_yoast_wpseo_metadesc' => $answer_meta,
    )
);

$post_id = wp_insert_post($post_arr);
$featured = set_post_thumbnail( $post_id, $featured_id );

Aplicación en Python para publicación automática diaria en WordPress

Aunque el plugin anterior podría haberlo creado con Python y quizá hubiese sido incluso más sencillo, me decidí por hacerlo todo en WordPress sin tener que recurrir a herramientas externas.

Para crear una aplicación que publique de forma programada del modo que yo quería he tenido que recurrir al uso de tecnologías externas. En este caso he usado un NAS, un script de Python que sube los datos mediante la REST API de WordPress y la programación de la tarea en el NAS mediante BASH.

Comparto el código del archivo de control de esta aplicación:

import openai
import base64
import requests
import json
import pandas as pd
from datetime import datetime
from datetime import timedelta
import sendinblue as sb
import get_img_leo as leo
import up_img_wp as up_img

#df = pd.read_csv('../py/articulos2.csv', usecols=[i for i in range(0,3) ], encoding="ISO-8859-1", sep=';')
sheet_url = 'https://docs.google.com/spreadsheets/d/iDdeNuEstroGoogleSHeeT/edit#gid=0'
url_1 = sheet_url.replace('/edit#gid=', '/export?format=csv&gid=')
df = pd.read_csv(url_1)
today = datetime.today().date()
two_days = today + timedelta(days=2)

two_days_article = 0
counter = 0

for date in df['date']:
    try:
        #print(titulo)
        sheet_date = datetime.strptime(date, "%d-%m-%y").date()
        #check if today has article to post

        if sheet_date == today:

            #img leo
            prompt_leo = df['img'][counter]
            img_leo = leo.img_gen_leo(prompt_leo, 448, 352)

            #upload the image
            img_uploaded = up_img.restImgUL(img_leo)
            img_json = json.loads(img_uploaded)
            img_id = str(img_json['id'])
            img_url = img_json['guid']['raw']

            img_code = '<!-- wp:group {"layout":{"type":"constrained"}' + '} -->\n<div class="wp-block-group"><!-- wp:image {"align":"right","id":' + img_id + ',"sizeSlug":"full","linkDestination":"none"} --><figure class="wp-block-image alignright size-full"><img src="' + img_url + '" alt="imagen impactante para web de piercings" class="wp-image-' + img_id + '"/></figure><!-- /wp:image -->'

            #create post
            openai.api_key = "APIKEY de OPENAI"
            titulo = df['title'][counter]

            #Titulo
            MODEL = "gpt-4"
            response = openai.ChatCompletion.create(
                model=MODEL,
                messages=[

                    {"role": "system", "content": "Eres una experta en copy y redacción para webs de [lo que queramos]"},
                    {"role": "user", "content": "Reescribe el siguiente título, con menos de 60 caracteres, y enfócate en hacerlo lo más atractivo posible: " + str(titulo)},
                ],
                temperature=0.7,
            )

            resp_titulo = response.choices[0].message["content"]
            resp_titulo = resp_titulo.replace('"', '')
            #metadescription
            MODEL = "gpt-4"

            response_meta = openai.ChatCompletion.create(
                model=MODEL,
                messages=[
                    {"role": "system", "content": "Eres una experta en copy y redacción para webs de [lo que queramos]"},
                    {"role": "user", "content": "Escribe una metadescription que no supere los 130 caracteres para un artículo llamado: " + str(titulo)},
                ],
                temperature=0.7,
            )

            metadescription = response_meta.choices[0].message["content"]
            #sections
            MODEL = "gpt-4"

            response = openai.ChatCompletion.create(
                model=MODEL,
                messages=[

                    {"role": "system", "content": "Adopta el rol de copywriter profesional especializada en el mundo de [lo que queramos] y devuelve lo que se te solicite en un único párrafo separando las unidades por comas y sin incluir el titulo"},

                    {"role": "user", "content": "Escribe solamente los títulos de las 5 secciones principales y más relevantes que debería llevar el artículo dirigido a [lo que queramos] con titulo: " + str(titulo)},
                ],
                temperature=0.7,
            )
            sections = response.choices[0].message["content"]

            #content
            MODEL = "gpt-4"

            response = openai.ChatCompletion.create(
                model=MODEL,

                messages=[
                    {"role": "system", "content": "Eres una experta en copy y redacción para webs de [lo que queramos]"},
                    {"role": "system", "content": "Debes crear el contenido en pequeños párrafos para facilitar la lectura"},
                    {"role": "system", "content": "Es vital que el contenido no sea reiterativo ni repetitivo"},
                    {"role": "system", "content": "Debes ser respetuosa en todo momento"},
                    {"role": "user", "content": "Genera un artículo completo en HTML incluyendo exclusivamente las etiquetas: <section>, <h2>, <h3>, <p>, <ul>, <li>, <strong>. Excluyendo etiquetas HTML <h1>. El artículo debe contar con un mínimo de 800 palabras y tiene el titulo '" + resp_titulo + "'. Se deben incluir secciones y subsecciones. El contenido de las secciones no debe ser reiterativo ni repetitivo, las secciones deben ser las siguientes: " + sections + ". Debe ser interesante para el usuario, con una jerarquía de encabezados, H2 y H3 en HTML, así como algún listado ul, acaba todas las frases aunque el texto se exceda del máximo. En este artículo se deben responder las principales dudas que tienen los usuarios en Google sobre este tema concreto, es decir, se deben responder sus preguntas frecuentes. Este artículo solo debe abarcar el tema concreto del que trata el título " + resp_titulo + ", sin abarcar temáticas más generales, aunque estén directamente relacionadas con ese título."},

                ],
                temperature=0.7,
            )

            summary = response.choices[0].message["content"]
            summary = summary.replace('"', '')
            summary = summary.replace('<section>', '<!-- wp:group {"layout":{"type":"constrained"}} --> <div class="wp-block-group">')
            summary = summary.replace('</section>', '</div> <!-- /wp:group -->')
            summary = summary.replace('<p>', '<!-- wp:paragraph --><p>')
            summary = summary.replace('</p>', '</p><!-- /wp:paragraph -->')
            summary = summary.replace('<ul>', '<!-- wp:list --> <ul>')
            summary = summary.replace('</ul>', '</ul> <!-- /wp:list -->')
            summary = summary.replace('<li>', '<!-- wp:list-item --> <li>')
            summary = summary.replace('</li>', '</li> <!-- /wp:list-item -->')
            summary = summary.replace('<h2>', '<!-- wp:heading --> <h2 class="wp-block-heading">')
            summary = summary.replace('</h2>', '</h2> <!-- /wp:heading -->')
            summary = summary.replace('<h3>', '<!-- wp:heading {"level":3} --> <h3 class="wp-block-heading">')
            summary = summary.replace('</h3>', '</h3> <!-- /wp:heading -->')
            summary = summary.replace('</header>', '')
            summary = summary.replace('<header>', '')
            summary = summary.split('<body>', 1)[1]
            summary = summary.split('</body>', 1)[0]
            summary = img_code + summary

            login = 'Alvaro Torres'

            password = 'Clave de Rest API de WordPress'
            url = 'https://nuestraweb.com/wp-json/wp/v2/posts'
            headers = {
                'Authorization': 'Basic ' + base64.b64encode(f"{login}:{password}".encode()).decode(),
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0'
            }

            data = {
                'title': resp_titulo,
                'content': summary,
                'featured_media': img_id,
                'status': 'publish',
                'meta': {
                    '_yoast_wpseo_metadesc': metadescription
                }
            }

            response = requests.post(url, headers=headers, json=data)
            post_json = json.loads(response)
            post_id = post_json['id']
            post_url = post_json['guid']['raw']

            if response.status_code != 201:
                print(response.status_code)
                print('Error al crear el post')

        if sheet_date == two_days:
            two_days_article += 1

    except Exception:
        print("Error general")

    counter += 1

if two_days_article == 0:
    sb.send_mail('Configure the article', '[nuestra web] Articles needs to be configured.\n <a href="https://docs.google.com/spreadsheets/d/NuestRoGooGleSheets/edit#gid=0">CLICK HERE</a>', '2 days left to finish configured articles', 'alvaro@mimail.com', 'Alvaro')

Si queréis usarlo deberéis modificar vuestro Google Sheet, la clave de la API de Openai, vuestro mail, sustituir [lo que queramos] por los datos de vuestro proyecto y los datos de REST API de vuestra web.

También habréis visto que se importan 2 módulos que no os sonarán:

import get_img_leo as leo
import up_img_wp as up_img

En realidad son los dos archivos donde he almacenado las clases de chatGPT y Leonardo.ai.

Todos los archivos los he guardado en una carpeta de un NAS y después he creado una tarea que ejecuta el archivo principal mediante un simple comando BASH:

cd /
cd volume1/Python/miproyecto
source env/bin/activate
python control_archivo_python.py

Repito, si alguien se queda con dudas solo tendrá que escribirme por LinkedIn y encantado estaré de ayudarle en lo que pueda.

Conclusión

Este ha sido un proyecto en el que he invertido mucho tiempo, sobre todo a nivel de planificación. Pero hay que tener en cuenta que para los siguientes proyectos ya tengo la mitad del trabajo hecho.

Los resultados están siendo mejores de lo esperado, y aunque eso no garantice el éxito real del proyecto, sí que soy bastante optimista. Eso sí, las técnicas de monetización no se basarán exclusivamente en publicidad o posts patrocinados, sino que voy a incluir un servicio bastante económico que estoy convencido que puede funcionar.


Álvaro Torres, además de llevar muchos años haciendo callo en el desarrollo web, es el fundador de WebHeroe, una agencia de desarrollo web especializada en personalización en WordPress. Se define como un friki de WordPress al que le encanta estrujarse los sesos para crear nuevos proyectos digitales que le compliquen la vida un poquito más.

¿No tienes una cuenta en wetopi?

Incluye servidores desarrollo Gratis.
Sin tarjeta de crédito.

Compara wetopi con tu hosting actual

Date de alta, pide una migración y compara.

Hacemos una copia de tu web gratis y sin esfuerzo por tu parte.

Sin letra pequeña.
Sin compromisos.
Sin tarjeta de crédito.