Facebook marketing API: How to get the optimization event - node.js

Using the NodeJs (and also the REST API) Facebook marketing API I'm trying to know which Ad Sets are optimizing which event (e,g, add_to_wishlist)
To do that I'm fetching all ad sets:
import bizSdk = require('facebook-nodejs-business-sdk'); // v8.0.0
bizSdk.FacebookAdsApi.init('myaccesstoken')
const adAccount = new bizSdk.AdAccount('act_XXXXX');
const adSets= await adAccount.getAdSets([bizSdk.AdSet.Fields.optimization_sub_event,bizSdk.AdSet.Fields.optimization_goal]);
I always get NONE for the optimization_sub_event field and VALUE or OFFSITE_CONVERSIONS for optimization_goal
More over, I tried to fetch ALL fields possible and look for my event names but without success.
Is there away to achieve that using the API?

Fetch the field promoted_object.
The value for a custom event will have this structure:
promoted_object: {
"application_id": "994*******818",
"custom_event_type": "OTHER",
"object_store_url": "http://play.google.com/store/apps/details?id=com.*****",
"custom_event_str": "my_custom_event_name" // this is what you want
}

Related

SMART on FHIR JavaScript API does not return JSON with out additional call to fetchAll for Observation in Cerner tutorial

I'm working on creating a SMART on FHIR application based on the Cerner tutorial at https://engineering.cerner.com/smart-on-fhir-tutorial/.
The following is called in example-smart-app.js
var patient = smart.patient;
var pt = patient.read();
var obv = smart.patient.api.fetchAll({
type: 'Observation',
query: {
code: {
$or: ['http://loinc.org|8302-2', 'http://loinc.org|8462-4',
'http://loinc.org|8480-6', 'http://loinc.org|2085-9',
'http://loinc.org|2089-1', 'http://loinc.org|55284-4']
}
}
});
I've modified slightly to the following:
<script>
fhirOnReady = function(smart) {
patient = smart.patient;
pt = patient.read();
var obv = smart.patient.api.fetchAll({
type: 'Observation',
query: {
code: {
$or: [
'http://loinc.org|8302-2',
'http://loinc.org|8462-4',
'http://loinc.org|8480-6',
'http://loinc.org|2085-9',
'http://loinc.org|2089-1',
'http://loinc.org|55284-4'
]
}
}
});
var populatePatientData = function(patient) {
$("#fname").html(patient.name[0].given);
$("#lname").html(patient.name[0].family);
$("#gender").html(patient.gender);
$("#dob").html(patient.birthDate);
}
$.when(pt, obv).fail(fhirOnError);
$.when(pt, obv).done(
function(patient, obv) {
populatePatientData(patient);
$("#patientJson").html(JSON.stringify(patient,undefined,2));
$("#patientSuccessMsg").html("<h1>Congratulations, you've also successfully loaded a patient using SMART on FHIR</h1>");
}
);
};
fhirOnError = function() {
$("#patientJson").html("An error occurred.\nThis is expected if you are looking at this page from a browser.");
};
FHIR.oauth2.ready(fhirOnReady, fhirOnError);
</script>
If I run the above using the SMART App Launcher at https://launch.smarthealthit.org/ everything seems to work as expected.
However, if I remove the call to smart.patient.api.fetchAll for the observations the patient JSON string is empty.
What is the correct way to get the entire patient resource using the SMART on FHIR JavaScript Library described at http://docs.smarthealthit.org/client-js/?
---EDIT ----------------------------------
If I try to implement using the code in the documentation at http://docs.smarthealthit.org/client-js/#smart-api I get the error shown below.
Code
<!-- index.html -->
<script src="./node_module/fhirclient/build/fhir-client.js"></script>
<script>
FHIR.oauth2.ready()
.then(client => client.request("Patient"))
.then(console.log)
.catch(console.error);
</script>
Error
Libraries are taken directly from the Cerner tutorial.
SMART apps usually have a "patient" in context that is already part of the data passed over to the system from which you are trying to elicit information. In this case you are trying to hit the Cerner FHIR server to get the observations linked to that Patient. Two things are possible at this point:
The Server may not have the Patient resource, which is why it is using the Id of the patient to fetch all observations
Check your smart SCOPEs, you may not be allowed to read Patient records in it's entirety.
Usually the FHIR endpoint can be deciphered using Fiddler following the launch sequence. As per the SMART exchange the CapabilityStatement is queried for the authorization and Token endpoints. If you are able to see the server then you can tack on the /Patient/id to get the resource but this means you have to have a valid token and the appropriate scope statements in place.

Cannot get documentid using pnp.sp.search in spfx app

In an older JavaScript app I used keyword-query to search for document properties, and I could add the 'DlcDocID' field (Document id) to be retrieved.
I am currently developing an Spfx version of the app, and use pnp.sp.search to get document data. This way I can get the UniqueId and the DocId, but not the Document Id. How can I have this parameter included in the search results?
Extra:
I am using 1.3.11, and this code
pnp.sp.search(
{
Querytext:query,
RowLimit:rows,
StartRow:start,
SelectProperties: ["DocId"
, "UniqueId"
,"FileType"
,"ServerRedirectedEmbedURL"
, "ServerRedirectedPreviewURL"
,"LastModifiedTime"
,"Write"
,"Size"
,"SPWebUrl"
,"ParentLink"
,"Title"
,"HitHighlightedSummary"
,"Path"
,"Author"
,"LastModifiedTime"
,"DlcDocID"
],
But DlcDocID is never retrieved.
Looking at the docs, DlcDocID should be retrievable (it's queryable and retrievable by default). Have you tried using SearchQueryBuilder and selectProperties?
const q = SearchQueryBuilder().text(yourQuery).
.rowLimit(10).processPersonalFavorites.selectProperties('*', 'DlcDocID');
const results = await sp.search(q);
SearchQueryBuilder reference
The issue was that the pnp
SearchResult interface didn't have the DlcDocID in this version. Adding it solved the problem.

Create custom API with strapi

I've a content type called continent. Which we the name suggests contains all the information about each continents. Strapi already created API endpoints for me like
continents/:id
But I want to search the continent by it's name since the general user won't be able to search by id
I've created the endpoint
continents/:continent_name
I've also created custom controller following documentation
const { sanitizeEntity } =
requiree('strapi-utils');
module.exports = {
async findOne(ctx) {
const { continent_name } = ctx.params;
const entity = await
strapi.services.continent.findOne({
continent_name
});
return sanitizeEntity(entity, { model:
continents });
And also exposed the API to public
But doesn't seem to anything
Just returns error
How am I supposed to do it
For your use case, you don't need to extend the model controller. You can just pass the continent name as a query param . For example, your url could be something like base_url/continent?continent_name=Asia.
For the code mentioned in the question, there is an issue, the model name should be strapi.models.continent and not continents. Also in the first line requiree('strapi-utils'), you have an extra e in the require. I am assuming that was just a typo.

Retrieve Documents from a Template

I created a template within my DocuSign developer Sandbox that contains one document. I'm using the C# SDK to try and send out an envelope to a user, based on a template.
Here's the code where I retrieve all of the templates.
TemplatesApi templateApi = new TemplatesApi(ApiClient.Configuration);
EnvelopeTemplateResults templateResults = templateApi.ListTemplates(AccountID);
The issue I am having is the EnvelopeTemplateResults does NOT have any documents associated with it.
When I use the REST API using POSTMAN, performing a GET to this URL, I can see that there's an envelopeTemplateDefinition, that has a Document on it, which is the one I want.
My question is, how, using the SDK API, can I get the envelopeTemplateDefinition ?
In order to have the ListTemplates method include the Documents info, you have to set an Include parameter:
var templatesApi = new TemplatesApi(apiClient.Configuration);
var listTemplatesOptions = new TemplatesApi.ListTemplatesOptions { include = "documents" };
var templateResults = templatesApi.ListTemplates(accountId, listTemplatesOptions);
If you are trying to get the Template Definition of a single template, the templatesApi.Get() method can be used with its own set of Include options:
var getTemplateOptions = new TemplatesApi.GetOptions { include = "documents" };
var templateDefinition = templatesApi.Get(accountId, templateId, getTemplateOptions);
Finally, if you're trying to get an actual PDF out of a specific template, that would be the templatesApi.GetDocument() method:
templatesApi.GetDocument(accountId, templateId, documentId);
Where DocumentId is the specific document you want to pull, or "Combined" if you want to pull all the documents in as a single PDF.
Chris, if you are using the v2 API, there's an endpoint:
GET /v2/accounts/{accountId}/templates/{templateId}/documents/{documentId}
you can try it here - https://apiexplorer.docusign.com/#/esign/restapi?categories=Templates&tags=TemplateDocuments&operations=get
the c# SDK inside TemplateAPI has GetDocument() and UpdateDocument() methods

Paging in MS Graph API

Graph API Paging explains that the response would contain a field #odata.nextLink which would contain a skiptoken pointing to the next page of contents.
When I test the API, I'm getting a fully-qualified MS Graph URL which contains the skiptoken as a query param. E.g. Below is the value I got for the field #odata.nextLink in the response JSON.
https://graph.microsoft.com/v1.0/users?$top=25&$skiptoken=X%27445370740200001E3A757365723134406F33363561702E6F6E6D6963726F736F66742E636F6D29557365725F31363064343831382D343162382D343961372D383063642D653136636561303437343437001E3A7573657235407368616C696E692D746573742E31626F74322E696E666F29557365725F62666639356437612D333764632D343266652D386335632D373639616534303233396166B900000000000000000000%27
Is it safe to assume we'll always get the full URL and not just the skiptoken? Because if it's true, it helps avoid parsing the skiptoken and then concatenating it to the existing URL to form the full URL ourselves.
EDIT - Compared to MS Graph API, response obtained from Azure AD Graph API differs in that the JSON field #odata.nextLink contains only the skipToken and not the fully-qualified URL.
if you would like to have all users in single list, you can achieve that using the code that follows:
public static async Task<IEnumerable<User>> GetUsersAsync()
{
var graphClient = GetAuthenticatedClient();
List<User> allUsers = new List<User>();
var users = await graphClient.Users.Request().Top(998)
.Select("displayName,mail,givenName,surname,id")
.GetAsync();
while (users.Count > 0)
{
allUsers.AddRange(users);
if (users.NextPageRequest != null)
{
users = await users.NextPageRequest
.GetAsync();
}
else
{
break;
}
}
return allUsers;
}
I am using graph client library
Yes. In Microsoft Graph you can assume that you'll always get the fully qualified URL for the #odata.nextLink. You can simply use the next link to get the next page of results, and clients should treat the nextLink as opaque (which is described in both OData v4 and in the Microsoft REST API guidelines here: https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md#98-pagination.
This is different from AAD Graph API (which is not OData v4), which doesn't return the fully qualified next link, and means you need to do some more complicated manipulations to get the next page of results.
Hence Microsoft Graph should make this simpler for you.
Hope this helps,
The above code did not work for me without adding a call to 'CurrentPage' on the last line.
Sample taken from here.
var driveItems = new List<DriveItem>();
var driveItemsPage = await graphClient.Me.Drive.Root.Children.Request().GetAsync();
driveItems.AddRange(driveItemsPage.CurrentPage);
while (driveItemsPage.NextPageRequest != null)
{
driveItemsPage = await driveItemsPage.NextPageRequest.GetAsync();
driveItems.AddRange(driveItemsPage.CurrentPage);
}
I followed Tracy's answer and I was able to fetch all the messages at one go.
public List<Message> GetMessages()
{
var messages = new List<Message>();
var pages = Client.Users[_email]
.Messages
.Request(QueryOptions)
// Fetch the emails with attachments directly instead of downloading them later.
.Expand("attachments")
.GetAsync()
.Result;
messages.AddRange(pages.CurrentPage);
while (pages.NextPageRequest != null)
{
pages = pages.NextPageRequest.GetAsync().Result;
messages.AddRange(pages.CurrentPage);
}
return messages;
}

Resources