Ti diamo il benvenuto su Tenor. Tenor adotta un approccio incentrato sui dati per fornire ricerche di GIF pertinenti in oltre 45 lingue in tutto il mondo. Integra la ricerca di GIF di Tenor nella tua applicazione in pochi minuti.

Punti salienti dell'API
La tastiera GIF di Tenor è l'app per la condivisione di GIF su mobile più scaricata. Gli sviluppatori possono incorporare ogni funzionalità di Tenor nelle proprie applicazioni con le nostre API. Ecco alcune delle caratteristiche principali:
Cerca GIF coinvolgenti e pertinenti su internet. |
Supporto di oltre 45 lingue, contenuti localizzati e idoneità dei contenuti regionali. |
Funzionalità avanzate che aiutano gli utenti a trovare rapidamente la GIF che desiderano. |
Ottimizzazione che offre GIF che vengono caricate e consumano meno larghezza di banda. |
Configurazione
Prima di iniziare, segui questi passaggi:
-
Registrati o accedi alla console Google Cloud
Puoi registrarti o accedere alla console Google Cloud e ottenere una chiave API Tenor senza costi per la tua app in meno di 60 secondi. Visualizza le metriche API e richiedi nuove chiavi tramite la console Google Cloud.
Attribuzione, limitazione della frequenza e memorizzazione nella cache
Devi attribuire correttamente tutti i contenuti recuperati da Tenor con una delle tre opzioni di attribuzione.
Assicurati di esaminare le norme relative ai limiti di frequenza e alla memorizzazione nella cache per l'API Tenor.
Cerca
Passaggio 1: implementa la ricerca
La ricerca di Tenor offre GIF pertinenti e coinvolgenti in oltre 45 lingue. Tenor riceve oltre 300 milioni di ricerche al giorno e migliora continuamente i risultati delle GIF per ogni query in base al comportamento di ricerca e condivisione degli utenti.
Ti consigliamo di caricare inizialmente una delle dimensioni ottimizzate più piccole per le anteprime, ad esempio
tinygif
. Successivamente, puoi caricare e visualizzare la versione a grandezza naturale, ad esempio
gif
, quando l'utente condivide.
Questa documentazione include esempi di richieste di ricerca nei suoi esempi di codice. Questi esempi utilizzano l'endpoint di ricerca e richiedono le prime otto GIF classificate per il termine di ricerca excited
.
Curl
/* search for excited top 8 GIFs */ curl "https://tenor.googleapis.com/v2/search?q=excited&key=API_KEY&client_key=my_test_app&limit=8"
Python
# set the apikey and limit apikey = "API_KEY" # click to set to your apikey lmt = 8 ckey = "my_test_app" # set the client_key for the integration and use the same value for all API calls # our test search search_term = "excited" # get the top 8 GIFs for the search term r = requests.get( "https://tenor.googleapis.com/v2/search?q=%s&key=%s&client_key=%s&limit=%s" % (search_term, apikey, ckey, lmt)) if r.status_code == 200: # load the GIFs using the urls for the smaller GIF sizes top_8gifs = json.loads(r.content) print(top_8gifs) else: top_8gifs = None
Android/Java
import android.app.Application; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringWriter; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; public class App extends Application { private static final String API_KEY = "API_KEY"; private static final String CLIENT_KEY = "my_test_app" private static final String LogTag = "TenorTest"; @Override public void onCreate() { super.onCreate(); new Thread() { @Override public void run() { final String searchTerm = "excited"; // make initial search request for the first 8 items JSONObject searchResult = getSearchResults(searchTerm, 8); // load the results for the user Log.v(LogTag, "Search Results: " + searchResult.toString()); } }.start(); } /** * Get Search Result GIFs */ public static JSONObject getSearchResults(String searchTerm, int limit) { // make search request - using default locale of EN_US final String url = String.format("https://tenor.googleapis.com/v2/search?q=%1$s&key=%2$s&client_key=%3$s&limit=%4$s", searchTerm, API_KEY, CLIENT_KEY, limit); try { return get(url); } catch (IOException | JSONException ignored) { } return null; } /** * Construct and run a GET request */ private static JSONObject get(String url) throws IOException, JSONException { HttpURLConnection connection = null; try { // Get request connection = (HttpURLConnection) new URL(url).openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.setRequestMethod("GET"); connection.setRequestProperty("Content-Type", "application/json"); connection.setRequestProperty("Accept", "application/json"); connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); // Handle failure int statusCode = connection.getResponseCode(); if (statusCode != HttpURLConnection.HTTP_OK && statusCode != HttpURLConnection.HTTP_CREATED) { String error = String.format("HTTP Code: '%1$s' from '%2$s'", statusCode, url); throw new ConnectException(error); } // Parse response return parser(connection); } catch (Exception ignored) { } finally { if (connection != null) { connection.disconnect(); } } return new JSONObject(""); } /** * Parse the response into JSONObject */ private static JSONObject parser(HttpURLConnection connection) throws JSONException { char[] buffer = new char[1024 * 4]; int n; InputStream stream = null; try { stream = new BufferedInputStream(connection.getInputStream()); InputStreamReader reader = new InputStreamReader(stream, "UTF-8"); StringWriter writer = new StringWriter(); while (-1 != (n = reader.read(buffer))) { writer.write(buffer, 0, n); } return new JSONObject(writer.toString()); } catch (IOException ignored) { } finally { if (stream != null) { try { stream.close(); } catch (IOException ignored) { } } } return new JSONObject(""); } }
Swift 2.0+/iOS
let apikey = "API_KEY" let clientkey = "my_test_app" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { requestData() return true } /** Execute web request to retrieve the top GIFs returned(in batches of 8) for the given search term. */ func requestData() { // the test search term let searchTerm = "excited" // Define the results upper limit let limit = 8 // make initial search request for the first 8 items let searchRequest = URLRequest(url: URL(string: String(format: "https://tenor.googleapis.com/v2/search?q=%@&key=%@&client_key=%@&limit=%d", searchTerm, apikey, clientkey, limit))!) makeWebRequest(urlRequest: searchRequest, callback: tenorSearchHandler) // Data will be loaded by each request's callback } /** Async URL requesting function. */ func makeWebRequest(urlRequest: URLRequest, callback: @escaping ([String:AnyObject]) -> ()) { // Make the async request and pass the resulting JSON object to the callback let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in do { if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] { // Push the results to our callback callback(jsonResult) } } catch let error as NSError { print(error.localizedDescription) } } task.resume() } /** Web response handler for search requests. */ func tenorSearchHandler(response: [String:AnyObject]) { // Parse the JSON response let responseGifs = response["results"]! // Load the GIFs into your view print("Result GIFS: (responseGifs)") }
JavaScript
<!DOCTYPE html> <html> <script> // url Async requesting function function httpGetAsync(theUrl, callback) { // create the request object var xmlHttp = new XMLHttpRequest(); // set the state change callback to capture when the response comes in xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { callback(xmlHttp.responseText); } } // open as a GET call, pass in the url and set async = True xmlHttp.open("GET", theUrl, true); // call send with no params as they were passed in on the url string xmlHttp.send(null); return; } // callback for the top 8 GIFs of search function tenorCallback_search(responsetext) { // Parse the JSON response var response_objects = JSON.parse(responsetext); top_10_gifs = response_objects["results"]; // load the GIFs -- for our example we will load the first GIFs preview size (nanogif) and share size (gif) document.getElementById("preview_gif").src = top_10_gifs[0]["media_formats"]["nanogif"]["url"]; document.getElementById("share_gif").src = top_10_gifs[0]["media_formats"]["gif"]["url"]; return; } // function to call the trending and category endpoints function grab_data() { // set the apikey and limit var apikey = "API_KEY"; var clientkey = "my_test_app"; var lmt = 8; // test search term var search_term = "excited"; // using default locale of en_US var search_url = "https://tenor.googleapis.com/v2/search?q=" + search_term + "&key=" + apikey +"&client_key=" + clientkey + "&limit=" + lmt; httpGetAsync(search_url,tenorCallback_search); // data will be loaded by each call's callback return; } // SUPPORT FUNCTIONS ABOVE // MAIN BELOW // start the flow grab_data(); </script> <body> <h2># 1 GIF loaded - preview image</h2> <img id="preview_gif" src="" alt="" style="width:220px;height:164px;"> <h2># 1 GIF loaded - share image</h2> <img id="share_gif" src="" alt="" style="width:498px;height:372px;"> </body> </html>
Objective-C
NSString *apiKey = @"API_KEY"; NSString *clientKey = @"my_test_app"; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self requestData]; return YES; } /** Execute web request to retrieve the top GIFs returned(in batches of 8) for the given search term. */ -(void)requestData { // Define the results upper limit int limit = 8; // the test search term NSString *searchQuery = @"excited"; // Get the top 10 trending GIFs (updated through out the day) - using the default locale of en_US NSString *UrlString = [NSString stringWithFormat:@"https://tenor.googleapis.com/v2/search?key=%@&client_key=%@&q=%@&limit=%d", apiKey, clientKey, searchQuery, limit]; NSURL *searchUrl = [NSURL URLWithString:UrlString]; NSURLRequest *searchRequest = [NSURLRequest requestWithURL:searchUrl]; [self makeWebRequest:searchRequest withCallback:tenorSearchResultsHandler]; // Data will be loaded by each request's callback } /** Async URL requesting function. */ -(void)makeWebRequest:(NSURLRequest *)urlRequest withCallback:(void (^)(NSDictionary *))callback { // Make the async request and pass the resulting JSON object to the callback NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NStopGifsError *jsonError = nil; NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError]; if(jsonError != nil) { NSLog(@"%@", jsonError.localizedDescription); return; } // Push the results to our callback callback(jsonResult); }]; [task resume]; } /** Web response handler for searches. */ void (^tenorSearchResultsHandler)(NSDictionary *) = ^void(NSDictionary *response) { // Parse the JSON response NSDictionary *topGifs = response[@"results"]; // Load the GIFs into your view NSLog(@"Search Results: %@", topGifs); };
Condividi
Passaggio 2: implementa gli eventi di condivisione
Quando un utente seleziona una GIF da condividere, invia un evento di condivisione corrispondente a Tenor. Gli eventi di condivisione aiutano l'AI del motore di ricerca di Tenor a perfezionare i risultati di ricerca, il che aiuta gli utenti a trovare la GIF perfetta.
L'esempio seguente utilizza l'endpoint Registra condivisione con il primo risultato GIF restituito per il termine di ricerca excited
:
Curl
/* register share */ curl "https://tenor.googleapis.com/v2/registershare?id=16989471141791455574&key=API_KEY&client_key=my_test_app&q=excited"
Python
# set the apikey apikey = "API_KEY" # click to set to your apikey ckey = "my_test_app" # set the client_key for the integration # get the GIF's id and search used shard_gifs_id = top_8gifs["results"][0]["id"] search_term = "excited" r = requests.get("https://tenor.googleapis.com/v2/registershare?id=%s&key=%s&client_key=%s&q=%s" % (shard_gifs_id, apikey, ckey, search_term)) if r.status_code == 200: pass # move on else: pass # handle error
Android/Java
import android.app.Application; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringWriter; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; public class App extends Application { private static final String API_KEY = "API_KEY"; private static final String CLIENT_KEY = "my_test_app"; private static final String LogTag = "TenorTest"; @Override public void onCreate() { super.onCreate(); new Thread() { @Override public void run() { // test values for the share example final String gifId = "16989471141791455574"; final String searchTerm = "excited"; // make the register share call JSONObject shareResult = registerShare(gifId, searchTerm); // load the results for the user Log.v(LogTag, "Share Results: " + shareResult.toString()); } }.start(); } /** * Register the GIF share */ public static JSONObject registerShare(String gifId, String searchTerm) { // make register share request - using default locale of EN_US final String url = String.format("https://tenor.googleapis.com/v2/registershare?key=%1$s&client_key=%2$s&id=%3$s&q=%4$s", API_KEY, CLIENT_KEY, gifId, searchTerm); try { return get(url); } catch (IOException | JSONException ignored) { } return null; } /** * Construct and run a GET request */ private static JSONObject get(String url) throws IOException, JSONException { HttpURLConnection connection = null; try { // Get request connection = (HttpURLConnection) new URL(url).openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.setRequestMethod("GET"); connection.setRequestProperty("Content-Type", "application/json"); connection.setRequestProperty("Accept", "application/json"); connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); // Handle failure int statusCode = connection.getResponseCode(); if (statusCode != HttpURLConnection.HTTP_OK && statusCode != HttpURLConnection.HTTP_CREATED) { String error = String.format("HTTP Code: '%1$s' from '%2$s'", statusCode, url); throw new ConnectException(error); } // Parse response return parser(connection); } catch (Exception ignored) { } finally { if (connection != null) { connection.disconnect(); } } return new JSONObject(""); } /** * Parse the response into JSONObject */ private static JSONObject parser(HttpURLConnection connection) throws JSONException { char[] buffer = new char[1024 * 4]; int n; InputStream stream = null; try { stream = new BufferedInputStream(connection.getInputStream()); InputStreamReader reader = new InputStreamReader(stream, "UTF-8"); StringWriter writer = new StringWriter(); while (-1 != (n = reader.read(buffer))) { writer.write(buffer, 0, n); } return new JSONObject(writer.toString()); } catch (IOException ignored) { } finally { if (stream != null) { try { stream.close(); } catch (IOException ignored) { } } } return new JSONObject(""); } }
Swift 2.0+/iOS
let apikey = "API_KEY" let clientkey = "my_test_app" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // test values for the share example let gifId = "16989471141791455574" let searchTerm = "excited" // register the user's share registerShare(gifId: gifId, searchTerm: searchTerm) return true } // Function for handling a user's selection of a GIF to share. // In a production application, the GIF id should be the "id" field of the GIF response object that the user selected // to share. The search term should be the user's last search. func registerShare(gifId: String, searchTerm: String) { // Register the user's share - using the default locale of en_US let shareRequest = URLRequest(url: URL(string: String(format: "https://tenor.googleapis.com/v2/registershare?key=%@&client_key=%@&id=%@&q=%@", apikey, clientkey, gifId, searchTerm))!) makeWebRequest(urlRequest: shareRequest, callback: tenorShareHandler) // Data will be loaded by each request's callback } /** Async URL requesting function. */ func makeWebRequest(urlRequest: URLRequest, callback: @escaping ([String:AnyObject]) -> ()) { // Make the async request and pass the resulting json object to the callback let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in do { if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] { // Push the results to our callback callback(jsonResult) } } catch let error as NSError { print(error.localizedDescription) } } task.resume() } /** Web response handler for search requests. */ func tenorShareHandler(response: [String:AnyObject]) { // no response expected from the registershare endpoint }
JavaScript
<!DOCTYPE html> <html> <script> // url Async requesting function function httpGetAsync(theUrl, callback) { // create the request object var xmlHttp = new XMLHttpRequest(); // set the state change callback to capture when the response comes in xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { callback(xmlHttp.responseText); } } // open as a GET call, pass in the url and set async = True xmlHttp.open("GET", theUrl, true); // call send with no params as they were passed in on the url string xmlHttp.send(null); return; } // callback for share event function tenorCallback_share(responsetext) { // no action is needed in the share callback } // function to call the register share endpoint function send_share(search_term,shared_gifs_id) { // set the apikey and limit var apikey = "API_KEY"; var clientkey = "my_test_app"; var share_url = "https://tenor.googleapis.com/v2/registershare?id=" + shared_gifs_id + "&key=" + apikey + "&client_key=" + clientkey + "&q=" + search_term; httpGetAsync(share_url,tenorCallback_share); } // SUPPORT FUNCTIONS ABOVE // MAIN BELOW // grab search term from cookies or some other storage search_term = "excited"; // GIF id from the shared gif // shared_gifs_id = gif_json_response_object_from_search["results"][0]["id"] shared_gifs_id = "16989471141791455574"; // example // send the share notifcation back to Tenor send_share(search_term,shared_gifs_id); alert("share sent!"); </script> <body> </body> </html>
Objective-C
NSString *apiKey = @"API_KEY"; NSString *clientKey = @"my_test_app"; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self requestData]; return YES; } /** Function for handling a user's selection of a GIF to share. In a production application, the GIF id should be the "id" field of the GIF response object that the user selected to share. The search term should be the user's last search. */ -(void)requestData { // the test search term NSString *searchQuery = @"excited"; NSString *gifId = @"16989471141791455574"; // Send the share event for the GIF id and search query NSString *UrlString = [NSString stringWithFormat:@"https://tenor.googleapis.com/v2/registershare?id=%d&key=%@&client_key=%@&q=%@", gifId, apiKey, clientKey, searchQuery]; NSURL *searchUrl = [NSURL URLWithString:UrlString]; NSURLRequest *searchRequest = [NSURLRequest requestWithURL:searchUrl]; [self makeWebRequest:searchRequest withCallback:tenorSearchResultsHandler]; // Data will be loaded by each request's callback } /** Async URL requesting function. */ -(void)makeWebRequest:(NSURLRequest *)urlRequest withCallback:(void (^)(NSDictionary *))callback { // Make the async request and pass the resulting json object to the callback NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NStopGifsError *jsonError = nil; NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError]; if(jsonError != nil) { NSLog(@"%@", jsonError.localizedDescription); return; } // Push the results to our callback callback(jsonResult); }]; [task resume]; } /** Web response handler for registered shares */ void (^tenorShareResultsHandler)(NSDictionary *) = ^void(NSDictionary *response) { // no response expected from the registershare endpoint. };
Complimenti! L'integrazione con l'API di Tenor è stata eseguita correttamente.

Ora miglioriamo l'esperienza.
Ricerca avanzata
Passaggio 3: arricchisci l'esperienza di ricerca
In questo passaggio, esaminiamo le best practice che contribuiscono a migliorare l'esperienza utente e ad aumentare le ricerche e le condivisioni dall'integrazione per GIF di Tenor.
R. Avviare l'esperienza di ricerca
Abbiamo scoperto che l'esperienza iniziale migliore è quella di visualizzare una casella di ricerca pulita. Dopo la casella di ricerca, visualizza le categorie di GIF, prese dall'endpoint Categorie, e i termini di ricerca di tendenza, presi dall'endpoint Termini di ricerca di tendenza. In alternativa, puoi visualizzare le GIF in primo piano dall'endpoint GIF in primo piano sotto la casella di ricerca.
Se vuoi, puoi utilizzare il parametro locale
con l'endpoint Categorie per adattare i risultati alla lingua locale. Il valore predefinito è en_US
.
Il seguente esempio recupera le categorie e le GIF in primo piano di Tenor da mostrare all'utente:
Curl
/* Featured GIFs call */ curl "https://tenor.googleapis.com/v2/featured?key=API_KEY&client_key=my_test_app" /* categories call */ curl "https://tenor.googleapis.com/v2/categories?key=API_KEY&client_key=my_test_app"
Python
import requests import json # set the apikey and limit apikey = "API_KEY" # click to set to your apikey ckey = "my_test_app" # set the client_key for the integration lmt = 10 # get the top 10 featured GIFs - using the default locale of en_US r = requests.get("https://tenor.googleapis.com/v2/featured?key=%s&client_key=%s&limit=%s" % (apikey, ckey, lmt)) if r.status_code == 200: featured_gifs = json.loads(r.content) else: featured_gifs = None # get the current list of categories - using the default locale of en_US r = requests.get("https://tenor.googleapis.com/v2/categories?key=%s&client_key=%s" % (apikey, ckey)) if r.status_code == 200: categories = json.loads(r.content) else: categories = None # load either the featured GIFs or categories below the search bar for the user # for GIFs use the smaller formats for faster load times print (featured_gifs) print (categories)
Android/Java
import android.app.Application; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringWriter; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; public class App extends Application { private static final String API_KEY = "API_KEY"; private static final String CLIENT_KEY = "my_test_app"; private static final String LogTag = "TenorTest"; @Override public void onCreate() { super.onCreate(); new Thread() { @Override public void run() { // get the top 10 featured GIFs JSONObject featuredGifs = getFeaturedGifs(10); // get the current list of categories JSONObject categories = getCategories(); // load the results for the user Log.v(LogTag, "Featured GIFS: " + featuredGifs.toString()); Log.v(LogTag, "GIF Categories: " + categories.toString()); } }.start(); } /** * Get featured GIFs */ public static JSONObject getFeaturedGifs(int limit) { // get the Featured GIFS - using the default locale of en_US final String url = String.format("https://tenor.googleapis.com/v2/featured?key=%1$s&client_key=%2$s&limit=%3$s", API_KEY, CLIENT_KEY, limit); try { return get(url); } catch (IOException | JSONException ignored) { } return null; } /** * Get categories */ public static JSONObject getCategories() { // get the categories - using the default locale of en_US final String url = String.format("https://tenor.googleapis.com/v2/categories?key=%1$s&client_key=%2$s", API_KEY, CLIENT_KEY); try { return get(url); } catch (IOException | JSONException ignored) { } return null; } /** * Construct and run a GET request */ private static JSONObject get(String url) throws IOException, JSONException { HttpURLConnection connection = null; try { // Get request connection = (HttpURLConnection) new URL(url).openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.setRequestMethod("GET"); connection.setRequestProperty("Content-Type", "application/json"); connection.setRequestProperty("Accept", "application/json"); connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); // Handle failure int statusCode = connection.getResponseCode(); if (statusCode != HttpURLConnection.HTTP_OK && statusCode != HttpURLConnection.HTTP_CREATED) { String error = String.format("HTTP Code: '%1$s' from '%2$s'", statusCode, url); throw new ConnectException(error); } // Parse response return parser(connection); } catch (Exception ignored) { } finally { if (connection != null) { connection.disconnect(); } } return new JSONObject(""); } /** * Parse the response into JSONObject */ private static JSONObject parser(HttpURLConnection connection) throws JSONException { char[] buffer = new char[1024 * 4]; int n; InputStream stream = null; try { stream = new BufferedInputStream(connection.getInputStream()); InputStreamReader reader = new InputStreamReader(stream, "UTF-8"); StringWriter writer = new StringWriter(); while (-1 != (n = reader.read(buffer))) { writer.write(buffer, 0, n); } return new JSONObject(writer.toString()); } catch (IOException ignored) { } finally { if (stream != null) { try { stream.close(); } catch (IOException ignored) { } } } return new JSONObject(""); } }
Swift 2.0+/iOS
let apikey = "API_KEY" let clientkey = "my_test_app" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { requestData() return true } /** Execute web requests to retrieve featured GIFs and GIF categories. */ func requestData() { // Define the results upper limit let limit = 10 // Get the top 10 featured GIFs (updated throughout the day) - using the default locale of en_US let featuredRequest = URLRequest(url: URL(string: String(format: "https://tenor.googleapis.com/v2/featured?key=%@&client_key=%@&limit=%d", apikey, clientkey, limit))!) makeWebRequest(urlRequest: featuredRequest, callback: tenorFeaturedResultsHandler) // Get the current list of categories - using the default locale of en_US let categoryRequest = URLRequest(url: URL(string: String(format: "https://tenor.googleapis.com/v2/categories?key=%@&client_key=%@", apikey, clientkey))!) makeWebRequest(urlRequest: categoryRequest, callback: tenorCategoryResultsHandler) // Data will be loaded by each request's callback } /** Async URL requesting function. */ func makeWebRequest(urlRequest: URLRequest, callback: @escaping ([String:AnyObject]) -> ()) { // Make the async request and pass the resulting JSON object to the callback let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in do { if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] { // Push the results to our callback callback(jsonResult) } } catch let error as NSError { print(error.localizedDescription) } } task.resume() } /** Web response handler for featured top 10 GIFs. */ func tenorFeaturedResultsHandler(response: [String:AnyObject]) { // Parse the JSON response let topTenGifs = response["results"]! // Load the GIFs into your view print("Featured Results: (topTenGifs)") } /** Web response handler for GIF categories. */ func tenorCategoryResultsHandler(response: [String:AnyObject]) { // Parse the JSON response let categories = response["tags"]! // Load the categories into your view print("Category Results: (categories)") } }
JavaScript
<!DOCTYPE html> <html> <script> // url Async requesting function function httpGetAsync(theUrl, callback) { // create the request object var xmlHttp = new XMLHttpRequest(); // set the state change callback to capture when the response comes in xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { callback(xmlHttp.responseText); } } // open as a GET call, pass in the url and set async = True xmlHttp.open("GET", theUrl, true); // call send with no params as they were passed in on the url string xmlHttp.send(null); return; } // callback for featured top 10 GIFs function tenorCallback_featured(responsetext) { // Parse the JSON response var response_objects = JSON.parse(responsetext); top_10_gifs = response_objects["results"]; // load the GIFs -- for our example we will load the first GIFs preview size (nanogif) and share size (gif) document.getElementById("preview_gif").src = top_10_gifs[0]["media_formats"]["nanogif"]["url"]; document.getElementById("share_gif").src = top_10_gifs[0]["media_formats"]["gif"]["url"]; return; } // callback for GIF categories function tenorCallback_categories(responsetext) { // Parse the JSON response var response_objects = JSON.parse(responsetext); categories = response_objects["tags"]; // load the categories - example is for the first category // url to load: var imgurl = categories[0]["image"]; // text to overlay on image: var txt_overlay = categories[0]["name"]; // search to run if user clicks the category var category_search_path = categories[0]["path"]; document.getElementById("category_gif").src = imgurl document.getElementById("catgif_caption").innerHTML = txt_overlay document.getElementById("cat_link").href = category_search_path return; } // function to call the featured and category endpoints function grab_data() { // set the apikey and limit var apikey = "API_KEY"; var clientkey = "my_test_app"; var lmt = 10; // get the top 10 featured GIFs (updated throughout the day) - using the default locale of en_US var featured_url = "https://tenor.googleapis.com/v2/featured?key=" + apikey + "&client_key=" + clientkey + "&limit=" + lmt; httpGetAsync(featured_url,tenorCallback_featured); // get the current list of categories - using the default locale of en_US var cat_url = "https://tenor.googleapis.com/v2/categories?key=" + apikey + "&client_key=" + clientkey; httpGetAsync(cat_url,tenorCallback_categories); // data will be loaded by each call's callback return; } // SUPPORT FUNCTIONS ABOVE // MAIN BELOW // start the flow grab_data(); </script> <style> .container { position: relative; text-align: center; color: white; } .title { text-align: center; } .centered { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } </style> <body> <h2 class="title">GIF loaded - preview image</h2> <div class="container"> <img id="preview_gif" src="" alt="" style=""> </div> <h2 class="title">GIF loaded - share image</h2> <div class="container"> <img id="share_gif" src="" alt="" style=""> </div> <h2 class="title">GIF Category</h2> <div class="container"> <a id="cat_link" href=""> <img id="category_gif" src="" alt="" style=""> <div id="catgif_caption" class="centered"></div> </a> </div> </body> </html>
Objective-C
NSString *apiKey = @"API_KEY"; NSString *clientKey = @"my_test_app"; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self requestData]; return YES; } /** Execute web requests to retrieve featured GIFs and GIF categories. */ -(void)requestData { // Define the results upper limit int limit = 10; // Get the top 10 featured GIFs (updated throughout the day) - using the default locale of en_US NSString *featuredUrlString = [NSString stringWithFormat:@"https://tenor.googleapis.com/v2/featured?key=%@&client_key=%@&limit=%d", apiKey, clientKey, limit]; NSURL *featuredUrl = [NSURL URLWithString:featuredUrlString]; NSURLRequest *featuredRequest = [NSURLRequest requestWithURL:featuredUrl]; [self makeWebRequest:featuredRequest withCallback:tenorFeaturedResultsHandler]; // Get the current list of categories - using the default locale of en_US NSString *categoryUrlString = [NSString stringWithFormat:@"https://tenor.googleapis.com/v2/categories?key=%@&client_key=%@", apiKey, clientKey]; NSURL *categoryUrl = [NSURL URLWithString:categoryUrlString]; NSURLRequest *categoryRequest = [NSURLRequest requestWithURL:categoryUrl]; [self makeWebRequest:categoryRequest withCallback:tenorCategoryResultsHandler]; // Data will be loaded by each request's callback } /** Async URL requesting function. */ -(void)makeWebRequest:(NSURLRequest *)urlRequest withCallback:(void (^)(NSDictionary *))callback { // Make the async request and pass the resulting JSON object to the callback NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSError *jsonError = nil; NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError]; if(jsonError != nil) { NSLog(@"%@", jsonError.localizedDescription); return; } // Push the results to our callback callback(jsonResult); }]; [task resume]; } /** Web response handler for featured top 10 GIFs. */ void (^tenorFeaturedResultsHandler)(NSDictionary *) = ^void(NSDictionary *response) { // Parse the JSON response NSDictionary *topTenGifs = response[@"results"]; // Load the GIFs into your view NSLog(@"Featured Results: %@", topTenGifs); }; /** Web response handler for GIF categories. */ void (^tenorCategoryResultsHandler)(NSDictionary *) = ^void(NSDictionary *response) { // Parse the JSON response NSDictionary *categories = response[@"tags"]; // Load the categories into your view NSLog(@"Category Results: %@", categories); };
B: Suggerimenti di completamento automatico
Se mostri agli utenti le opzioni di ricerca con completamento automatico mentre digitano, gli utenti possono completare le ricerche di GIF più rapidamente, il che aumenta l'utilizzo e la fidelizzazione delle GIF.
Ti consigliamo di trasmettere almeno due caratteri e le impostazioni internazionali dell'utente. Il parametro
locale
adatta i risultati alla lingua locale. Il valore predefinito è
en_US
.
Il seguente esempio chiama l'endpoint di completamento automatico con un termine di ricerca parziale di exc
. I risultati sono ordinati in base alla probabilità di generare una quota
per un determinato termine parziale.
Curl
/* autocomplete */ curl "https://tenor.googleapis.com/v2/autocomplete?key=API_KEY&client_key=my_test_app&q=exc"
Python
apikey = "API_KEY" # click to set to your apikey ckey = "my_test_app" # set the client_key for the integration lmt = 5 # partial search psearch = "exc" r = requests.get( "https://tenor.googleapis.com/v2/autocomplete?key=%s&client_key=%s&q=%s&limit=%s" % (apikey, ckey, psearch, lmt)) if r.status_code == 200: # return the search predictions search_term_list = json.loads(r.content)["results"] print(search_term_list) else: # handle a possible error search_term_list = []
Android/Java
import android.app.Application; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringWriter; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; public class App extends Application { private static final String API_KEY = "API_KEY"; private static final String CLIENT_KEY = "my_test_app"; private static final String LogTag = "TenorTest"; @Override public void onCreate() { super.onCreate(); new Thread() { @Override public void run() { // for testing, the partial search final String partialSearch = "exc"; int limit = 5; // make the autocomplete call JSONObject autoCompleteResult = autoCompleteRequest(partialSearch, limit); // load the results for the user Log.v(LogTag, "AutoComplete Results: " + autoCompleteResult.toString()); } }.start(); } /** * Autocomplete Request */ public static JSONObject autoCompleteRequest(String partialSearch, int limit) { // make an autocomplete request - using default locale of EN_US final String url = String.format("https://tenor.googleapis.com/v2/autocomplete?key=%1$s&client_key=%2$s&q=%3$s&limit=%4$s", API_KEY, CLIENT_KEY, partialSearch, limit); try { return get(url); } catch (IOException | JSONException ignored) { } return null; } /** * Construct and run a GET request */ private static JSONObject get(String url) throws IOException, JSONException { HttpURLConnection connection = null; try { // Get request connection = (HttpURLConnection) new URL(url).openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.setRequestMethod("GET"); connection.setRequestProperty("Content-Type", "application/json"); connection.setRequestProperty("Accept", "application/json"); connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); // Handle failure int statusCode = connection.getResponseCode(); if (statusCode != HttpURLConnection.HTTP_OK && statusCode != HttpURLConnection.HTTP_CREATED) { String error = String.format("HTTP Code: '%1$s' from '%2$s'", statusCode, url); throw new ConnectException(error); } // Parse response return parser(connection); } catch (Exception ignored) { } finally { if (connection != null) { connection.disconnect(); } } return new JSONObject(""); } /** * Parse the response into JSONObject */ private static JSONObject parser(HttpURLConnection connection) throws JSONException { char[] buffer = new char[1024 * 4]; int n; InputStream stream = null; try { stream = new BufferedInputStream(connection.getInputStream()); InputStreamReader reader = new InputStreamReader(stream, "UTF-8"); StringWriter writer = new StringWriter(); while (-1 != (n = reader.read(buffer))) { writer.write(buffer, 0, n); } return new JSONObject(writer.toString()); } catch (IOException ignored) { } finally { if (stream != null) { try { stream.close(); } catch (IOException ignored) { } } } return new JSONObject(""); } }
Swift 2.0+/iOS
let apikey = "API_KEY" let clientkey = "my_test_app" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { requestData() return true } /** Execute web requests to get autocomplete suggestions. */ func requestData() { // for testing, the partial search let partialSearch = "exc" let limit = 5 // Get up to 5 results from the autocomplete suggestions - using the default locale of en_US let autoRequest = URLRequest(url: URL(string: String(format: "https://tenor.googleapis.com/v2/autocomplete?key=%@&client_key=%@&q=%@&limit=%d", apikey, clientkey, partialSearch, limit))!) makeWebRequest(urlRequest: autoRequest, callback: tenorAutoCompleteResultsHandler) // Data will be loaded by each request's callback } /** Async URL requesting function. */ func makeWebRequest(urlRequest: URLRequest, callback: @escaping ([String:AnyObject]) -> ()) { // Make the async request and pass the resulting JSON object to the callback let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in do { if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] { // Push the results to our callback callback(jsonResult) } } catch let error as NSError { print(error.localizedDescription) } } task.resume() } /** Web response handler for autocomplete requests. */ func tenorAutoCompleteResultsHandler(response: [String:AnyObject]) { // Parse the JSON response let autoSuggestions = response["results"]! // Load the GIFs into your view print("Autocomplete Results: (autoSuggestions)") } }
JavaScript
<!DOCTYPE html> <html> <script> // url Async requesting function function httpGetAsync(theUrl, callback) { // create the request object var xmlHttp = new XMLHttpRequest(); // set the state change callback to capture when the response comes in xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { callback(xmlHttp.responseText); } } // open as a GET call, pass in the url and set async = True xmlHttp.open("GET", theUrl, true); // call send with no params as they were passed in on the url string xmlHttp.send(null); return; } // callback for share event function tenorCallback_autocomplete(responsetext) { var response_objects = JSON.parse(responsetext); predicted_words = response_objects["results"]; document.getElementById("ac_1").innerHTML = predicted_words[0]; document.getElementById("ac_2").innerHTML = predicted_words[1]; } // SUPPORT FUNCTIONS ABOVE // MAIN BELOW //partial search term psearch_term = "exc"; // set the apikey and limit var apikey = "API_KEY"; var clientkey = "my_test_app"; var lmt = 5; // using default locale of en_US var autoc_url = "https://tenor.googleapis.com/v2/autocomplete?key=" + apikey + "&client_key=" + clientkey + "&q=" + psearch_term + "&limit=" + lmt; // send autocomplete request httpGetAsync(autoc_url,tenorCallback_autocomplete); </script> <body> <h2>Partial Search "exc":</h2> <h3 id = "ac_1"></h3> <h3 id = "ac_2"></h3> </body> </html>
Objective-C
NSString *apiKey = @"API_KEY"; NSString *clientKey = @"my_test_app"; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self requestData]; return YES; } /** Execute web requests to get autocomplete suggestions. */ -(void)requestData { // Define the results upper limit int limit = 8; // the test search term NSString *partialSearch = @"exc"; // Get the auto complete predictions for the given partial search - using the default locale of en_US NSString *UrlString = [NSString stringWithFormat:@"https://tenor.googleapis.com/v2/autocomplete?key=%@&client_key=%@&q=%@&limit=%d", apiKey, clientKey, partialSearch, limit]; NSURL *searchUrl = [NSURL URLWithString:UrlString]; NSURLRequest *searchRequest = [NSURLRequest requestWithURL:searchUrl]; [self makeWebRequest:searchRequest withCallback:tenorAutoCompleteResultsHandler]; // Data will be loaded by each request's callback } /** Async URL requesting function. */ -(void)makeWebRequest:(NSURLRequest *)urlRequest withCallback:(void (^)(NSDictionary *))callback { // Make the async request and pass the resulting JSON object to the callback NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NStopGifsError *jsonError = nil; NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError]; if(jsonError != nil) { NSLog(@"%@", jsonError.localizedDescription); return; } // Push the results to our callback callback(jsonResult); }]; [task resume]; } /** Web response handler for auto complete predictions */ void (^tenorAutoCompleteResultsHandler)(NSDictionary *) = ^void(NSDictionary *response) { // Parse the JSON response NSDictionary *results = response[@"results"]; // Load the GIFs into your view NSLog(@"Auto Complete Result: %@", results); };
C: Suggerimenti di ricerca
I suggerimenti per la ricerca aiutano un utente a restringere i termini di ricerca correlati alla ricerca o alla scoperta per trovare una GIF più precisa.
Spesso gli utenti non sanno esattamente cosa stanno cercando e i suggerimenti di ricerca li aiutano a correggere gli errori ortografici o a trovare termini più simili.
L'API restituisce i risultati in ordine di probabilità di condivisione di una GIF per un determinato termine.
Il seguente esempio restituisce i primi cinque suggerimenti di ricerca per il termine di ricerca
smile
:
Curl
/* search suggestion */ curl "https://tenor.googleapis.com/v2/search_suggestions?key=API_KEY&client_key=my_test_app&q=smile&limit=5"
Python
# set the apikey and limit the # coming back apikey = "API_KEY" # click to set to your apikey ckey = "my_test_app" # set the client_key for the integration lmt = 5 # partial search search = "smile" r = requests.get( "https://tenor.googleapis.com/v2/search_suggestions?key=%s&client_key=%s&q=%s&limit=%s" % (apikey, ckey, search, lmt)) if r.status_code == 200: # return the search suggestions search_suggestion_list = json.loads(r.content)["results"] print search_suggestion_list else: # handle a possible error search_suggestion_list = []
Android/Java
import android.app.Application; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringWriter; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; public class App extends Application { private static final String API_KEY = "API_KEY"; private static final String CLIENT_KEY = "my_test_app"; private static final String LogTag = "TenorTest"; @Override public void onCreate() { super.onCreate(); new Thread() { @Override public void run() { // for testing, the last search final String lastSearch = "smile"; int limit = 5; // make the search suggestion call JSONObject searchSuggestionResult = searchSuggestionRequest(lastSearch, limit); // load the results for the user Log.v(LogTag, "Search Suggestion Results: " + searchSuggestionResult.toString()); } }.start(); } /** * Autocomplete Request */ public static JSONObject searchSuggestionRequest(String lastSearch, int limit) { // make an autocomplete request - using default locale of EN_US final String url = String.format("https://tenor.googleapis.com/v2/search_suggestions?key=%1$s&client_key=%2$s&q=%3$s&limit=%4$s", API_KEY, CLIENT_KEY, lastSearch, limit); try { return get(url); } catch (IOException | JSONException ignored) { } return null; } /** * Construct and run a GET request */ private static JSONObject get(String url) throws IOException, JSONException { HttpURLConnection connection = null; try { // Get request connection = (HttpURLConnection) new URL(url).openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.setRequestMethod("GET"); connection.setRequestProperty("Content-Type", "application/json"); connection.setRequestProperty("Accept", "application/json"); connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); // Handle failure int statusCode = connection.getResponseCode(); if (statusCode != HttpURLConnection.HTTP_OK && statusCode != HttpURLConnection.HTTP_CREATED) { String error = String.format("HTTP Code: '%1$s' from '%2$s'", statusCode, url); throw new ConnectException(error); } // Parse response return parser(connection); } catch (Exception ignored) { } finally { if (connection != null) { connection.disconnect(); } } return new JSONObject(""); } /** * Parse the response into JSONObject */ private static JSONObject parser(HttpURLConnection connection) throws JSONException { char[] buffer = new char[1024 * 4]; int n; InputStream stream = null; try { stream = new BufferedInputStream(connection.getInputStream()); InputStreamReader reader = new InputStreamReader(stream, "UTF-8"); StringWriter writer = new StringWriter(); while (-1 != (n = reader.read(buffer))) { writer.write(buffer, 0, n); } return new JSONObject(writer.toString()); } catch (IOException ignored) { } finally { if (stream != null) { try { stream.close(); } catch (IOException ignored) { } } } return new JSONObject(""); } }
Swift 2.0+/iOS
let apikey = "API_KEY" let clientkey = "my_test_app" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { requestData() return true } /** Execute web requests to get search suggestions. */ func requestData() { // for testing, the partial search let lastsearch = "smile" let limit = 5 // Get the top 5 search suggestions - using the default locale of en_US let suggestRequest = URLRequest(url: URL(string: String(format: "https://tenor.googleapis.com/v2/search_suggestions?key=%@&client_key=%@&q=%@&limit=%d", apikey, clientkey, lastsearch, limit))!) makeWebRequest(urlRequest: suggestRequest, callback: tenorSuggestResultsHandler) // Data will be loaded by each request's callback } /** Async URL requesting function. */ func makeWebRequest(urlRequest: URLRequest, callback: @escaping ([String:AnyObject]) -> ()) { // Make the async request and pass the resulting JSON object to the callback let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in do { if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] { // Push the results to our callback callback(jsonResult) } } catch let error as NSError { print(error.localizedDescription) } } task.resume() } /** Web response handler for search suggestion requests. */ func tenorSuggestResultsHandler(response: [String:AnyObject]) { // Parse the JSON response let searchSuggestion = response["results"]! // Load the GIFs into your view print("Search Suggestion Results: (searchSuggestion)") } }
JavaScript
<!DOCTYPE html> <html> <script> // url Async requesting function function httpGetAsync(theUrl, callback) { // create the request object var xmlHttp = new XMLHttpRequest(); // set the state change callback to capture when the response comes in xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { callback(xmlHttp.responseText); } } // open as a GET call, pass in the url and set async = True xmlHttp.open("GET", theUrl, true); // call send with no params as they were passed in on the url string xmlHttp.send(null); return; } // callback for share event function tenorCallback_searchSuggestion(responsetext) { var response_objects = JSON.parse(responsetext); predicted_words = response_objects["results"]; document.getElementById("ac_1").innerHTML = predicted_words[0]; document.getElementById("ac_2").innerHTML = predicted_words[1]; document.getElementById("ac_3").innerHTML = predicted_words[2]; document.getElementById("ac_4").innerHTML = predicted_words[3]; } // SUPPORT FUNCTIONS ABOVE // MAIN BELOW //search term psearch_term = "smile"; // set the apikey and limit var apikey = "API_KEY"; var clientkey = "my_test_app"; var lmt = 5; // using default locale of en_US var autoc_url = "https://tenor.googleapis.com/v2/search_suggestions?key=" + apikey + "&client_key=" + clientkey + "&q=" + psearch_term + "&limit=" + lmt; // send search suggestion request httpGetAsync(autoc_url,tenorCallback_searchSuggestion); </script> <body> <h2>Search Suggestion for "smile":</h2> <h3 id = "ac_1"></h3> <h3 id = "ac_2"></h3> <h3 id = "ac_3"></h3> <h3 id = "ac_4"></h3> </body> </html>
Objective-C
NSString *apiKey = @"API_KEY"; NSString *clientKey = @"my_test_app"; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self requestData]; return YES; } /** Execute web requests to get search suggestions. */ -(void)requestData { // Define the results upper limit int limit = 5; // the test search term NSString *lastSearch = @"smile"; // Get the search suggestions for the given last search - using the default locale of en_US NSString *UrlString = [NSString stringWithFormat:@"https://tenor.googleapis.com/v2/search_suggestions?key=%@&client_key=%@&q=%@&limit=%d", apiKey, clientKey, lastSearch, limit]; NSURL *searchUrl = [NSURL URLWithString:UrlString]; NSURLRequest *searchRequest = [NSURLRequest requestWithURL:searchUrl]; [self makeWebRequest:searchRequest withCallback:tenorSearchSuggestionResultsHandler]; // Data will be loaded by each request's callback } /** Async URL requesting function. */ -(void)makeWebRequest:(NSURLRequest *)urlRequest withCallback:(void (^)(NSDictionary *))callback { // Make the async request and pass the resulting JSON object to the callback NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NStopGifsError *jsonError = nil; NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError]; if(jsonError != nil) { NSLog(@"%@", jsonError.localizedDescription); return; } // Push the results to our callback callback(jsonResult); }]; [task resume]; } /** Web response handler for search suggestions */ void (^tenorSearchSuggestionResultsHandler)(NSDictionary *) = ^void(NSDictionary *response) { // Parse the JSON response NSDictionary *results = response[@"results"]; // Load the GIFs into your view NSLog(@"Search Suggestion Result: %@", results); };