Importación

Es probable que en muchos casos ya dispongamos de una lista de suscriptores en formato CSV o similar. Insertar estos contactos uno a uno como se mostró en la sección Contactos no es una buena opción, necesitamos procesarlos en forma masiva.

Para poder hacerlo de una manera práctica y eficiente, existe la función de importación. Además, la importación funciona como una tarea asincrónica, tal como se explicó en la sección Tareas.

Atención! El usuario tiene la obligación, tal como lo establecen los términos y condiciones del servicio, de utilizar listas de suscriptores Opt-In. Es decir, que cada uno de los contactos optó por recibir las comunicaciones que se le enviarán. No está permitido el uso de listas de terceros, recolectadas en Internet o compradas.

Origen de los datos

Lo primero que debemos saber es de que manera vamos a proporcionar los datos en crudo.

Existen 2 alternativas:

  • Subir un archivo local, previamente al pedido de importación.
  • Incluir los datos en el mismo pedido de importación.

Upload de un archivo

Cuando disponemos de los datos en un archivo local, lo primero que hay que hacer es subir este archivo a través de la API para que quede disponible para su procesamiento. Para esto, debemos hacer un POST a /:account/contacts/import/upload. El formato del pedido debe ser multipart/form-data, y el nombre del parámetro debe ser fileToUpload.

La respuesta de la API será algo así:

{
  "href": "/v2/micuenta/contacts/import/upload",
  "success": true,
  "data": {
    "id": "mi-archivo.csv"
  }
}

Debemos recordar el campo id, que hace referencia al archivo que acabamos de subir. Lo usaremos a continuación en el pedido de import. En este caso tiene el mismo nombre que el archivo original, pero podría diferir.

Para poder entender mejor el ejemplo, supongamos que el contenido del archivo es el siguiente:

email,nombre,apellido
jsmith@example.org,John,Smith
rdoe@example.org,Richard,Doe

Enviar los datos en la misma acción de import

Cuando los datos no superen los 20kB, podemos incluirlos en la misma acción de importación, a través del parámetro sourceRaw que se detallará mas adelante.

Previsualización

La acción de preview permite ver como se procesarán las primeras líneas de un archivo. De esta manera podemos probar con distintas configuraciones para obtener los resultados esperados.

El preview procesa los datos en forma sincrónica, o sea que no genera ninguna tarea, tendremos los resultados de inmediato.

Se realiza haciendo un POST a /:account/contacts/import/preview. Los parámetros que recibe el preview son exactamente iguales a los del import definitivo.

Por ejemplo, si queremos hacer un preview del archivo subido en el paso anterior:

$sample = file_get_contents(
    'https://api.myperfit.com/v2/micuenta/contacts/import/preview',
    false,
    stream_context_create(['http'=> [
        'method'=>'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n" .
                    'X-Auth-Token: Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s',
        'content' => http_build_query([
            'type' => 'CSV',
            'mode' => 'OVERWRITE',
            'sourceFile' => 'mi-archivo.csv'
        ])
    ]])
);
$.ajax({
    type: 'POST',
    url: 'https://api.myperfit.com/v2/micuenta/contacts/import/preview',
    headers: { X-Auth-Token: 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s' },    
    data: {
        type: 'CSV',
        mode: 'OVERWRITE',
        sourceFile: 'mi-archivo.csv'
    },
    success: function (response) {
        var data = response.data;
    }
});

El resultado obtenido será algo así:


{
  "href": "/v2/micuenta/contacts/import/preview",
  "success": true,
  "data": {
    "options": {
      "mode": "OVERWRITE",
      "type": "CSV",
      "list": 0,
      "interests": [],
      "interestDefaultExpirationDays": null,
      "normalizeCase": false,
      "columnFields": [ 3, 1, 2 ],
      "sourceRaw": null,
      "sourceFile": "mi-archivo.csv",
      "columnHeaders": true,
      "interestColumn": null,
      "sourceFileEncoding": "ISO-8859-1",
      "stringDelimiter": "DOUBLE_QUOTES",
      "columnSeparator": "COMMA",
      "dateFormat": "dd/mm/yyyy"
    },
    "headers": ["email", "nombre", "apellido"],
    "original": [
      [ "jsmith@example.org", "John", "Smith" ],
      [ "rdoe@example.org", "Richard", "Doe" ]
    ],
    "preview": [
      [ "jsmith@example.org", "John", "Smith" ],
      [ "rdoe@example.org", "Richard", "Doe" ]
    ],
    "interests": [
      [],
      []
    ],
    "errors": [
      "",
      ""
    ]
  }
}

Veamos como interpretar este resultado.

En primer lugar está el elemento options. Aquí se indican las opciones utilizadas para realizar el preview. Algunas de las opciones fueron indicadas en el pedido inicial, el resto son valores inferidos o por defecto. Veremos en detalle cada opción más adelante.

Luego está headers, donde se indican los encabezados de las columnas del archivo, en caso que existan. Se puede ver que la opción columnHeaders está en true, este valor se infirió en forma automática, e indica que la primer fila corresponde con los nombres de las columnas.

El elemento original muestra los valores del archivo que subimos previamente.

En preview vemos como se importarán los datos en el import definitivo. En este caso son iguales, pero podrían no serlo dependiende de las opciones indicadas, como normalizeCase, columnFields o dateFormat.

El elemento interests indica los intereses que se asignarán a cada contacto, si se utilizó la opción interestsColumn. En este caso no fue indicado.

Y por último, errors muestra un detalle de los errores que se encontraron en cada una de las líneas a importar.

El tamaño los arrays original, preview, interests, errors concuerda en tamaño y orden con filas procesadas.

Importación

Las opciones para realizar la importación son:

  • type: Requerido. Indica el tipo de importación. Por el momento sólo se soporta CSV.

  • mode: Requerido. Indica la acción a tomar en caso que el contacto ya exista en la base. Puede ser OVERWRITE, DONT_MODIFY o IGNORE.

    • OVERWRITE: sólo se pisan los campos que se seleccionan en el import, los demás no se modifican.
    • DONT_MODIFY: no se modifica ningún campo del contacto, pero se suscriben la lista y los intereses.
    • IGNORE: el contacto se ignora por completo, no se suscribe a la lista ni se asignan intereses.
  • list: Opcional. Indica el id de la lista a la cual suscribir los contactos. Si se omite o se indica el id 0, no se asignan a ninguna lista.

  • interests: Opcional. Array con los ids de los intereses a asignar a los contactos importados. Si el contacto ya existe y tiene intereses asociados, los nuevos intereses se suman a los actuales.

  • interestDefaultExpirationDays: Opcional. Indica el tiempo de expiración a usar para los nuevos intereses, creados a partir de la opción interestColumn. Por defecto en 0 (no expiran nunca).

  • normalizeCase: Opcional, Boolean. indica si se normalizan las mayúsculas de los nombres y apellidos (por ej "DIEGO" se convierte a "Diego")

  • columnFields: Opcional. Indica los ids de los campos que corresponden con cada columna. Si no se desea importar una columna, se indica el valor 0. Si no se indica nada, se intentará inferir.

Las opciones específicas para el tipo CSV:

  • sourceRaw: Opcional, máx 20kB. Puede indicarse el contenido directamente como un string. Tener cuidado de encodear correctamente los caracteres especiales (como el retorno de carro) utilizando url encoding. Sólo puede indicarse sourceFile o sourceRaw, no ambos.

  • sourceFile: Opcional. Indica el archivo a utilizar como fuente de datos. Se asume que el archivo ya fue subido. Sólo puede indicarse sourceFile o sourceRaw, no ambos.

  • sourceFileEncoding: Opcional. Indica el tipo de encoding del archivo. Por defecto se utiliza ISO-8859-1, otras opciones son: UTF-8 y US-ASCII.

  • columnHeaders: Opcional. Indica si la primer fila contiene los nombres de las columnas. Esta información ayuda a inferir la correspondencia con los campos y además no se incluirá la línea en la importación. Si no se indica se intentará inferir.

  • columnSeparator: Opcional. Indica el separador de columnas a usar. Si no se indica se intenta inferir. Valores posibles: COMMA (,), SEMICOLON (;), TAB.

  • stringDelimiter: Opcional. Indica el delimitador de cadenas de texto. Si no se indica se intenta inferir. Valores posibles: QUOTES, DOUBLE_QUOTES.

  • dateFormat: Opcional. Especifica el formato a usar para las columnas de tipo fecha. Si no se especifica se utiliza el valor por defecto dd/mm/yyyy. Se utiliza el mismo formato para todos los campos de tipo fecha.

  • interestsColumn: Opcional. Indica la columna a usar para asignarle intereses particulares a cada contacto. Se toma el contenido de esta columna como nombre del interés, pudiendo incluir varios separados por coma. Si no existe el interés, se crea un nuevo, con tiempo de expiración interestDefaultExpirationDays.

Una vez definidas las opciones de importación, con la ayuda del preview, ya estamos en condiciones de lanzar la importación definitiva. Para esto debemos hacer un POST a /:account/contacts/import indicando las mismas opciones.

Por ejemplo:

$sample = file_get_contents(
    'https://api.myperfit.com/v2/micuenta/contacts/import',
    false,
    stream_context_create(['http'=> [
        'method'=>'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n" .
                    'X-Auth-Token: Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s',
        'content' => http_build_query([
            'type' => 'CSV',
            'mode' => 'OVERWRITE',
            'list' => 1,
            'sourceFile' => 'mi-archivo.csv',
            'columnFields' => array(3, 1, 2),
            'columnHeaders' => true
        ])
    ]])
);
$.ajax({
    type: 'POST',
    url: 'https://api.myperfit.com/v2/micuenta/contacts/import',
    headers: { X-Auth-Token: 'Shjg23Asd4Sdg8fd23F4eg8rF83kgd2s' },    
    data: {
        type: 'CSV',
        mode: 'OVERWRITE',
        list: 1,
        sourceFile: 'mi-archivo.csv',
        columnFields: [3, 1, 2],
        columnHeaders: true
    },
    success: function (response) {
        var data = response.data;
    }
});

En este caso, el resultado que obtendremos de inmediato es la creación de la nueva tarea, pendiente de ejecución:

{
  "href": "/v2/micuenta/contacts/import",
  "success": true,
  "task": {
    "id": 29656215,
    "type": "IMPORT",
    "name": "Importación de lista",
    "state": "QUEUED",
    "cancellable": true,
    "message": "Pendiente de ejecución",
    "owner": "usuario",
    "created": "2015-08-25T14:45:37.551+0000",
    "init": null,
    "end": null,
    "completed": 0,
    "eta": -1,
    "request": "/v2/micuenta/contacts/import",
    "parameters": {
      "mode": "OVERWRITE",
      "type": "CSV",
      "list": 1,
      "interests": [],
      "interestDefaultExpirationDays": null,
      "normalizeCase": false,
      "columnFields": [ 3, 1, 2 ],
      "sourceRaw": null,
      "sourceFile": "mi-archivo.csv",
      "columnHeaders": true,
      "interestColumn": null,
      "sourceFileEncoding": "ISO-8859-1",
      "stringDelimiter": null,
      "columnSeparator": null,
      "dateFormat": null
    },
    "result": null
  }
}

Como vemos, el estado inicial de la tarea es QUEUED, podemos consultar el estado y progreso de la tarea utilizando su id, como se explicó en la sección Tareas.

Resultados

Una vez finalizada la tarea, al hacer un GET a /micuenta/tasks/29656215 veremos algo así:

{
  "href": "/v2/micuenta/tasks/29656215",
  "success": true,
  "data": {
    "id": 29656215,
    "type": "IMPORT",
    "name": "Importación de lista",
    "state": "COMPLETED",
    "cancellable": false,
    "message": "Importación finalizada",
    "owner": "usuario",
    "created": "2015-08-25T14:45:37.000+0000",
    "init": "2015-08-25T14:54:33.000+0000",
    "end": "2015-08-25T14:54:42.000+0000",
    "completed": 1,
    "eta": 0,
    "request": "/v2/micuenta/contacts/import",
    "parameters": {
      "mode": "OVERWRITE",
      "type": "CSV",
      "list": 1,
      "interests": [],
      "interestDefaultExpirationDays": null,
      "normalizeCase": false,
      "columnFields": [ 3, 1, 2 ],
      "sourceRaw": null,
      "sourceFile": "mi-archivo.csv",
      "columnHeaders": true,
      "interestColumn": null,
      "sourceFileEncoding": "ISO-8859-1",
      "stringDelimiter": null,
      "columnSeparator": null,
      "dateFormat": null
    },
    "result": {
      "inserted": 2,
      "ignored": 0,
      "updated": 0,
      "failed": 0,
      "insertedReport": "/v2/micuenta/contacts/import/reports/inserted-29656215.csv",
      "ignoredReport": "/v2/micuenta/contacts/import/reports/ignored-29656215.csv",
      "updatedReport": "/v2/micuenta/contacts/import/reports/updated-29656215.csv",
      "failedReport": "/v2/micuenta/contacts/import/reports/failed-29656215.csv"
    }
  }
}

Lo mas interesante de esta respuesta es el elemento result, donde podemos ver el número y detalle de los contactos insertados, ignorados, actualizados y con errores. Para poder descargar el detalle debemos incluir también el token de autenticación ya que es un recurso privado.

Y esto es todo! Los nuevos contactos ya están disponibles en la lista seleccionada.