Spanish (Español) translation by Elías Nicolás (you can also view the original English article)
El
programa Amazon Associates, junto con Amazon Web Services (AWS), ofrece
a los desarrolladores un poderoso medio para buscar en el catálogo de
Amazon Store utilizando una API RESTful e integrar datos para casi
cualquier listado de productos en una página web. Si
eres un programador con una mentalidad de negocios y buscando formas de
monetizar tu sitio, puedes registrarte para ser un afiliado de Amazon y
ganar una comisión cada vez que un usuario haga clic en el enlace de
producto y complete una compra. (Y en cuanto a los programas de ingresos de afiliados, las comisiones de Amazon están entre las más generosas.)
Para aquellos de ustedes que son nuevos a la idea de marketing de afiliación, supongamos que están ejecutando un blog o sitio web con críticas de películas. Para cada revisión de la película que se publica, puede beneficiarse mediante la inclusión de un enlace para los lectores a comprar la película en algún lugar cerca de su artículo. Para que sea más atractivo hacer clic, el enlace puede incluir una imagen en miniatura del DVD, el nombre completo de la película, el precio más bajo disponible y un botón "Comprar".
En este tutorial, le mostraré cómo crear una clase dedicada y reutilizable en PHP que se conecta a la Product Merchandising API y extrae datos XML basados en el nombre del producto y la categoría de compras (en este caso "Películas"). Al final, vamos a rellenar los datos en una pequeña plantilla HTML completamente personalizable para que acabemos con una demostración de trabajo de un módulo de mini afiliados. Empecemos.
[Tenga
en cuenta antes de acceder a la demostración de ejemplo que si usted
opta por comprar o alquilar el DVD desde el enlace proporcionado,
resultará en un pago de comisión a Envato Tuts+.]
Registro de un ID de afiliado y obtención de credenciales
Primero, regístrese para una cuenta en affiliate-program.amazon.com. Es gratis, y sólo tienes que seguir los pasos para crear un perfil para tu sitio web. Se le pedirá que verifique su identidad al final del proceso ingresando su número de teléfono, recibiendo una llamada automatizada e ingresando el código de acceso que le entregan.
Una vez que haya completado el registro, se le dará un ID de afiliado de Amazon (en este ejemplo, es "envtuts-20"). Inicie sesión en su área de cuenta principal con su nombre de usuario y contraseña y haga clic en la ficha Product Merchandising API. Allí, haga clic en el enlace para empezar a usar la API.
Tendrá que registrarse en Amazon Web Services (aws.amazon.com), si aún no lo ha hecho. En la consola de AWS, en Credenciales de seguridad, puede generar una clave de acceso y clave secreta para realizar solicitudes de API. (Nota: es importante mantener estas credenciales privadas y seguras, nunca exponerlas públicamente en GitHub o en cualquier otro sitio en línea).
Configuración de nuestra PHP Helper Class
Para
los propósitos de este ejemplo y para mantener las cosas relativamente
sencillas, implementaremos el patrón de diseño de Singleton para crear
una clase auxiliar estática llamada AmazonAssocHelper
. Incluirá
un método público que se conecta a la API, busca en el catálogo y
devuelve los datos del producto utilizando ciertos parámetros que
pasamos. Así es como lo configuro:
1 |
<?php
|
2 |
|
3 |
|
4 |
namespace App\Services; |
5 |
|
6 |
use App\lib\vendor\aws\AWSSignedRequest; |
7 |
|
8 |
|
9 |
class AmazonAssocHelper { |
10 |
|
11 |
//AMAZON AFFILIATE PROGRAM ACCESS -- sign into affiliate-program.amazon.com
|
12 |
const AMZ_ASSOC_TAG = 'your-affiliate-id'; |
13 |
|
14 |
//AWS credentials -- sign into aws.amazon.com
|
15 |
const AMZ_ASSOC_ACCESSKEY = 'YOUR_ACCESS_KEY'; |
16 |
const AMZ_ASSOC_SECRETKEY = 'YOUR_SECRET_KEY'; |
17 |
|
18 |
//Set the values for some of the search parameters
|
19 |
private static $operation = "ItemSearch"; |
20 |
private static $version = "2013-08-01"; |
21 |
private static $response_group = "Small,Images,OfferSummary"; |
22 |
|
23 |
protected function __construct() { |
24 |
|
25 |
}
|
26 |
|
27 |
/**
|
28 |
* Fetches relevant product data in product API from keyphrase and category
|
29 |
* returns: array of data from the top result node
|
30 |
*/
|
31 |
public static function fetch_product_data($keyphrase, $category) { |
32 |
|
33 |
$result_xml = self::get_search_results($keyphrase, $category); |
34 |
|
35 |
//return an array containing the item name, link, image, and price
|
36 |
return self::get_top_result_data($result_xml); |
37 |
|
38 |
}
|
39 |
|
40 |
|
41 |
}
|
El primer par de líneas declaran un namespace para nuestra clase e incluyen una clase de terceros que necesitaremos para hacer una solicitud firmada a la API con nuestras credenciales. Las tres constantes que he definido son nuestros ID de afiliado, que obtuvimos después de registrarnos, y la clave de acceso y clave secreta de AWS. Cuando hacemos nuestras solicitudes de API, el ID de afiliado se inserta automáticamente en el vínculo de producto que recuperamos para que las compras se puedan rastrear adecuadamente a nuestra cuenta y ¡nos pagan! Asegúrese de llenar los tres valores para usted.
Las tres variables privadas se refieren a los parámetros de búsqueda que suministraremos para cada solicitud. Estoy usando "ItemSearch" como nuestra opción de operación para buscar resultados. "2013-08-01" es la fecha de la última versión de la API, que también debemos proporcionar a nuestra solicitud firmada y, por último, debemos designar los grupos de respuesta que nos gustaría devolver. Hay 55 opciones en total, y varían en tamaño y tipo de datos devueltos. Para nuestros propósitos, estamos buscando el título completo de la película y la URL completa de la página de detalles, ambas pertenecientes al grupo de respuestas "Pequeñas". También necesitamos una imagen en miniatura del grupo de respuestas "Images" y el precio nuevo más bajo del grupo "OfferSummary".
La función fetch_product_data()
es nuestro método públicamente expuesto que toma dos parámetros:
- Una frase clave específica que se refiere al nombre del producto que queremos buscar
- Una categoría de producto de Amazon aceptada
En última instancia, devolverá un conjunto de datos pertenecientes al primer resultado de búsqueda analizado desde una respuesta XML. (En muchos casos, el primer resultado será el producto que deseamos, suponiendo que la frase clave que suministramos sea lo suficientemente específica como alternativa, puede decidir modificar este ejemplo para buscar por el número ASIN o ID específico del producto En cambio, pero hay ventajas y desventajas de este método. Si usted tiene una gran base de datos de páginas de artículos para diferentes películas, utilizando un enfoque basado en nombres probablemente resultará más eficiente, ya que le permitirá generar automáticamente enlaces de productos para todos sus artículos al instante y ahorrarle tiempo extra y Esfuerzo de tener que buscar manualmente e insertar IDs para cada uno.)
Generación de una solicitud firmada
El siguiente paso es agregar una helper class que haga la solicitud firmada a la API del producto. Utilicé
una función de terceros escrita por Ulrich Mierendorff y la envolvió en
su propia clase estática llamada AWSSignedRequest
. Se
necesitan varios parámetros, incluyendo la región (para la tienda de
los Estados Unidos, usamos "com"), un array de parámetros de
solicitud, nuestras claves AWS, grupos de respuesta y la versión de la
API que ya hemos definido. El método get_signed_request()
esencialmente crea y devuelve una cadena de solicitud de URL completa de todas estas piezas.
La URL final de la solicitud firmada se verá así:
1 |
http://webservices.amazon.com/onca/xml? |
2 |
AWSAccessKeyId=AKIAJILHUTAJ5MMQRJWA |
3 |
&AssociateTag=envtut-20 |
4 |
&Operation=ItemSearch |
5 |
&ResponseGroup=Small%2CImages%2COfferSummary |
6 |
&SearchIndex=Movies |
7 |
&Service=AWSECommerceService |
8 |
&Timestamp=2015-11-06T20%3A34%3A52Z |
9 |
&Title=Jurassic%20World |
10 |
&Version=2013-08-01 |
11 |
&Signature=nwkfvvLCvl11Cunuthz6orXCbBMnBc1Z7S3HSfYW%2B14%3D |
En
la clase AmazonAssocHelper
, coloque la llamada a get_signed_request()
en un método llamado get_search_results()
y pase una matriz que
contenga cuatro parámetros de búsqueda ($params
) junto con los otros
argumentos como se muestra a continuación:
1 |
/**
|
2 |
* Runs search with signed request on product API using keyphrase and category name
|
3 |
* returns: XML object
|
4 |
*/
|
5 |
private static function get_search_results($keyphrase, $search_index) { |
6 |
|
7 |
//Define the request
|
8 |
$params = array("SearchIndex"=>$search_index, //the category |
9 |
"Title"=>$keyphrase, |
10 |
"Operation"=>self::$operation, |
11 |
"ResponseGroup"=>self::$response_group); |
12 |
|
13 |
$request = AWSSignedRequest::get_signed_request('com', $params, self::AMZ_ASSOC_ACCESSKEY, self::AMZ_ASSOC_SECRETKEY, self::AMZ_ASSOC_TAG, self::$version); |
14 |
|
15 |
$response = file_get_contents($request); |
16 |
|
17 |
//for testing
|
18 |
/*header('Content-type: application/xml');
|
19 |
echo $response;
|
20 |
exit;*/
|
21 |
|
22 |
return simplexml_load_string($response); |
23 |
|
24 |
}
|
Nuestra array $params
incluye la operación y la respuesta que ya hemos
definido, así como los valores de 'Title' y 'SearchIndex'. En este caso, SearchIndex es simplemente la categoría de producto en la que estamos buscando. Ahora,
podemos invocar la función de file_get_contents()
incorporada de PHP
para generar una respuesta de la petición, y como la respuesta es un
documento XML, usamos otra función incorporada, simplexml_load_string()
, para cargarla como un objeto que nosotros podamos usar.
Prueba de la respuesta y previsualización de datos XML
En
este punto, queremos poder probar nuestra solicitud de API con algunos
valores reales de producto para que podamos ver un ejemplo real de lo
que nuestros datos XML devueltos se ven antes de mostrarlos. Como
se muestra arriba, agregue unas líneas de prueba para establecer el
encabezado en application / XML e muestre $response
antes de que se
devuelva.
Ahora, cree un archivo que servirá como la página principal donde se mostrará el enlace del producto. He decidido llamarlo index.php. En la parte superior, agregue el siguiente código:
1 |
<?php
|
2 |
|
3 |
namespace App\Services; |
4 |
|
5 |
require_once getcwd() . '/App/app_global.php'; |
6 |
|
7 |
/**
|
8 |
* Call the Product API by passing in the name of the product and the shopping category
|
9 |
* ("Books", "Movies", and "VideoGames" are examples -- see API documentation for full list)
|
10 |
*/
|
11 |
$product_data = AmazonAssocHelper::fetch_product_data("Jurassic World", "Movies"); |
12 |
|
13 |
|
14 |
?>
|
Las
dos primeras líneas declaran nuestro espacio de nombres e incluyen una
función global que permite que nuestros archivos de clase se
auto-carguen, ya que no estamos usando un framework PHP. La siguiente línea es la importante. Llamamos
al método público fetch_product_data()
en nuestra clase
AmazonAssocHelper
y lo asignamos a una variable de matriz llamada $product_data
, pasando un nombre de película específico como frase clave
(elegi "Jurassic World" en la lista actual de best sellers) y "Películas" como la categoría.
Al cargar su página, el principio de su respuesta XML debería tener el siguiente aspecto:
1 |
<ItemSearchResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2013-08-01"> |
2 |
<OperationRequest>
|
3 |
<RequestId>807ede04-f196-44a0-99ff-ff1bb1c12fee</RequestId> |
4 |
<Arguments>
|
5 |
<Argument Name="AWSAccessKeyId" Value="AWS_ACCESS_KEY"/> |
6 |
<Argument Name="AssociateTag" Value="envtut-20"/> |
7 |
<Argument Name="Operation" Value="ItemSearch"/> |
8 |
<Argument Name="ResponseGroup" Value="Small,Images,OfferSummary"/> |
9 |
<Argument Name="SearchIndex" Value="Movies"/> |
10 |
<Argument Name="Service" Value="AWSECommerceService"/> |
11 |
<Argument Name="Timestamp" Value="2015-11-03T21:32:57Z"/> |
12 |
<Argument Name="Title" Value="Jurassic World"/> |
13 |
<Argument Name="Version" Value="2013-08-01"/> |
14 |
<Argument Name="Signature" Value="QhUpga/f2MReU4xpdzCr432hMvxeA72N+v+G0hVi17M="/> |
15 |
</Arguments>
|
16 |
<RequestProcessingTime>0.0887890000000000</RequestProcessingTime> |
17 |
</OperationRequest>
|
18 |
<Items>
|
19 |
<Request>...</Request> |
20 |
<TotalResults>37</TotalResults> |
21 |
<TotalPages>4</TotalPages> |
22 |
<MoreSearchResultsUrl>...</MoreSearchResultsUrl> |
23 |
<Item>
|
24 |
<ASIN>B016W01EXI</ASIN> |
25 |
<DetailPageURL>
|
26 |
http://www.amazon.com/Jurassic-World-Chris-Pratt/dp/B016W01EXI%3FSubscriptionId%3DAKIAJILHUTAJ5MMQRJWA%26tag%3Denvtut-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB016W01EXI |
27 |
</DetailPageURL>
|
28 |
<ItemLinks>
|
29 |
<ItemLink>
|
30 |
<Description>Technical Details</Description> |
31 |
<URL>
|
32 |
http://www.amazon.com/Jurassic-World-Chris-Pratt/dp/tech-data/B016W01EXI%3FSubscriptionId%3DAKIAJILHUTAJ5MMQRJWA%26tag%3Denvtut-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB016W01EXI |
33 |
</URL>
|
34 |
</ItemLink>
|
Si
se desplaza y escanea la salida, debería poder ver todos los datos que
serán útiles para nuestra demo, incluyendo , <DetailPageURL>
<Title>
<LargeImage>
<LowestNewPrice>
. Estos son los nodos que nos centraremos en analizar.
Mostrar el objeto de respuesta
En
la clase AmazonAssocHelper
, cree otro método llamado
get_top_result_data()
que tome nuestro objeto de respuesta XML como
parámetro. Ahora podemos empezar a leer los nodos
que contienen los datos que queremos capturar, pero antes de ir allí,
vamos a planificar la incorporación de algunos errores de verificación. He añadido
un par de líneas en la parte superior de nuestra función para invocar un
método que se encargará de analizar los nodos de error para nosotros, y
lo repasaré con más detalle hacia el final de este tutorial.
1 |
/**
|
2 |
* Parses top result node, and its attributes, from XML object
|
3 |
* returns: array of product data
|
4 |
*/
|
5 |
private static function get_top_result_data($xml) { |
6 |
|
7 |
if (!empty(self::handle_errors($xml))) { |
8 |
return array('error'=>self::handle_errors($xml)); |
9 |
}
|
10 |
|
11 |
//get the first result node
|
12 |
$first_item = $xml->Items[0]->Item; |
13 |
$item_title = $first_item->ItemAttributes->Title; |
14 |
$item_link = $first_item->DetailPageURL; |
15 |
$item_image = $first_item->LargeImage->URL; |
16 |
$item_price = $first_item->OfferSummary->LowestNewPrice->FormattedPrice; |
17 |
|
18 |
return array( 'title'=>(string)$item_title, |
19 |
'link'=>(string)$item_link, |
20 |
'image'=>(string)$item_image, |
21 |
'price'=>(string)$item_price ); |
22 |
|
23 |
|
24 |
|
25 |
}
|
Como
se puede ver en el código anterior, comenzamos recuperando el primer
nodo de elemento (Item[0]
) del objeto XML y almacenándolo en una
variable ($first_item
). Luego,
operamos en cada uno de sus hijos para recoger las piezas de
información que queremos ($item_title
, $item_link
, $item_image
, $item_price
). Finalmente, lo empacamos todo en un array con atributos nombrados y devolvemos la array.
Manejo de errores
Cree un método denominado handle_errors()
y pase el mismo objeto XML. En
función de la configuración de esta API, se configuran múltiples nodos
de error con códigos y mensajes específicos para que aparezcan en el
nodo <OperationRequest>
o en el nodo Items <Request>
. Puede probarlos estableciendo un índice de búsqueda no válido o un grupo de respuestas. El siguiente código pasa a través de cada uno de los nodos y empuja los mensajes de error en un array que devolvemos:
1 |
/**
|
2 |
* Checks for errors in the request/ result
|
3 |
* returns: array with message(s) describing the "error"
|
4 |
*/
|
5 |
private static function handle_errors($xml) { |
6 |
|
7 |
$errors_arr = array(); |
8 |
|
9 |
//process errors in request
|
10 |
foreach ($xml->OperationRequest->Errors->Error as $error) { |
11 |
|
12 |
error_log("Error code: " . $error->Code . "\r\n"); |
13 |
error_log($error->Message . "\r\n"); |
14 |
error_log("\r\n"); |
15 |
|
16 |
array_push($errors_arr, (string)$error->Message); |
17 |
}
|
18 |
|
19 |
//check for invalid category, no matches, or other search error
|
20 |
foreach ($xml->Items->Request->Errors->Error as $error) { |
21 |
|
22 |
error_log("Error code: " . $error->Code . "\r\n"); |
23 |
error_log($error->Message . "\r\n"); |
24 |
error_log("\r\n"); |
25 |
|
26 |
array_push($errors_arr, (string)$error->Message); |
27 |
}
|
28 |
|
29 |
|
30 |
return $errors_arr; |
31 |
|
32 |
}
|
Cómo rellenar los datos en una plantilla de HTML
En este punto, puede eliminar las llamadas de prueba XML, ya que estamos listos para ver la salida final de datos. En index.php, muestre la array $product_data
devuelta y cargue la página. Debería ver algo como esto:
1 |
Array ( [title] => Jurassic World [link] => http://www.amazon.com/Jurassic-World-Chris-Pratt/dp/B016W01EXI%3FSubscriptionId%3DAKIAJILHUTAJ5MMQRJWA%26tag%3Denvtut-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB016W01EXI [image] => http://ecx.images-amazon.com/images/I/51ePeFXU2ML.jpg [price] => $5.99 ) |
Una vez que haya verificado que los datos parecen correctos para cada una de las cuatro propiedades que nos interesan, puede intentar ejecutar la llamada en otras películas o productos para comparación. Tenga en cuenta que el ID de afiliado (en este caso "envtut-20") se ha insertado automáticamente en el "vínculo" como debemos esperar.
Como último paso, programemos un simple bloque de HTML para mostrar nuestros datos de película y hacer que se vincule a la página de compra. En index.php, agregue lo siguiente debajo del bloque PHP:
1 |
<!doctype html>
|
2 |
<html>
|
3 |
<head>
|
4 |
<title>Tuts+ Demo: Amazon Product API</title> |
5 |
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"> |
6 |
<link rel="stylesheet" href="css/reset.css" /> |
7 |
<link rel="stylesheet" href="css/style.css" /> |
8 |
</head>
|
9 |
<body>
|
10 |
<?php if (!empty($product_data) && array_key_exists("error", $product_data) != 1): ?>
|
11 |
<div class="affiliate_wrap"> |
12 |
|
13 |
<a href="<?php echo $product_data['link']; ?>" target="_blank"> |
14 |
<img src="<?php echo $product_data['image']; ?>" alt="<?php echo $product_data['title']; ?>" /> |
15 |
</a>
|
16 |
<h2>
|
17 |
<a href="<?php echo $product_data['link']; ?>" target="_blank"><?php echo $product_data['title']; ?></a> |
18 |
</h2>
|
19 |
<p><em><?php echo $product_data['price']; ?></em> on Amazon</p> |
20 |
<a class="button" href="<?php echo $product_data['link']; ?>" target="_blank">Buy Now</a> |
21 |
</div>
|
22 |
|
23 |
<?php endif ?>
|
24 |
</body>
|
25 |
</html>
|
Tenga en cuenta que en caso de que se devuelva un error, he optado por ocultar la visualización en conjunto, pero alternativamente, podría mostrar el mensaje de error adecuado en su lugar.
Ahora, con estilos CSS añadidos, la salida final se vería algo como esto:

¡Y ahí lo tienes! Una
vez que haya lanzado su módulo de afiliados en el mundo, puede realizar
un seguimiento de todas las compras y ganancias al iniciar sesión en su
cuenta.
Conclusion
En este tutorial, cubrimos todos los pasos necesarios para que un programador PHP construya una solución de código escalable que genere instantáneamente un vínculo de afiliado personalizado para virtualmente cualquier producto en la tienda de Amazon. Según sus necesidades o preferencias, puede decidir cambiar o ampliar este ejemplo con diferentes parámetros.
También puede explorar la documentación de la API con más detalle por su cuenta para descubrir aún más de lo que es posible. El verdadero poder en el uso de la Product Merchandising API reside en la flexibilidad que proporciona para organizar y mostrar una gama completa de información en tiempo real sobre un producto o una lista de productos. Con el generador de vínculos predeterminado de Amazon (no se requiere conocimientos de programacion), no obtiene casi la misma cantidad de control y sus opciones son limitadas.
La API realmente brilla en las páginas web que se generan dinámicamente y en las páginas donde se necesita un mayor nivel de control sobre la apariencia de sus enlaces, por lo que si está trabajando en un sitio web o blog a lo largo de estas líneas y buscando incorporar la monetización, espero que haya encontrado este tutorial útil.