Communications
APIs for content creation and management such as email, templates, mobile/feed posts, delivery, and more.
Integrating with a Feed
Overview
A feed is a collection of content - or posts - that is displayed on your integration.
The aim of this guide is to demonstrate how to configure a React based web client to make a GraphQL request to bring back information from your feed.
The guide assumes some basic understanding of programming and in particular javascript/typescript and React applications.
Note on Authorization
See the follow guide for details on how to get an Access Token to Authorize access to the GraphQL APIs Authorization
Getting posts from a feed
We can use the getPosts query to retrieve posts from our feed, note that this query uses pagination.
query myQuery {
getPosts {
totalCount
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
edges {
node {
id
author
body
title
status
}
cursor
}
}
}
This query will return something like the following:
{
"data": {
"getPosts": {
"totalCount": 4,
"pageInfo": {
"startCursor": "1uR7priuQj5KxWJ9ucbudJCdyhT",
"endCursor": "1tLEzOKjpSJXhjqms18MNIbZHhR",
"hasPreviousPage": false,
"hasNextPage": true
},
"edges": [
{
"node": {
"id": "3b1f3770-d59f-11eb-b0dc-614e46742993",
"author": null,
"body": ["<p>test</p>"],
"title": "Test Video Draft",
"status": "PUBLISHED"
},
"cursor": "1uR7priuQj5KxWJ9ucbudJCdyhT"
},
{
"node": {
"id": "842cf950-d597-11eb-b5ac-01eae0f19eeb",
"author": "tara",
"body": ["<p>nothin</p>"],
"title": "another test",
"status": "PUBLISHED"
},
"cursor": "1uR0mRfyOqzw5vnSnIKAaiCkXBt"
},
{
"node": {
"id": "7c36b4c0-d434-11eb-bb01-15bad062969f",
"author": null,
"body": ["<p>image draft post</p>"],
"title": "image draft post",
"status": "PUBLISHED"
},
"cursor": "1uM1timYXLsSQzGKeaI99WSaZRT"
},
{
"node": {
"id": "c4151a30-d433-11eb-bb01-15bad062969f",
"author": null,
"body": ["<p>draft post</p>"],
"title": "draft post",
"status": "PUBLISHED"
},
"cursor": "1uM1Xqv6DX4bZWakjtYwonKQEFX"
}
]
}
}
}
Now we can set up a client to execute this query against the platform api.
GraphQL Client setup
For this guide we're going to use Apollo's GraphQL client but any http client can be used as long as the following headers are set correctly:
- authorization: bearer token
- x-channel-id: integration uuid
- x-channel-version: integration / application version
Following Apollo's guidelines, we can set the headers using setContext
.
const authLink = setContext((_, { headers }) => {
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
authorization: `Bearer ${getToken()}`,
'x-channel-id': '123e4567-e89b-12d3-a456-426614174000',
'x-channel-version': '1.2.3',
},
};
});
This is what the completed index.ts
file should look like. We can use ApolloProvider
to inject the client throughout the application.
getToken
function requires a valid API token, which can be copied from the developer portalCopy API Token
buttonHttpLink
needs to point to eitherhttps://api.eu.poppulo-app.com/graphql
for the EU orhttps://api.us.poppulo-app.com/graphql
for the US - depending on where your Poppulo enterprise account is hosted.
import { setContext } from '@apollo/client/link/context';
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { ApolloClient, ApolloProvider, HttpLink, InMemoryCache } from '@apollo/client';
const httpLink = new HttpLink({
// ToDo: Confirm which region your enterprise account is hosted in and comment in the correct API you wish to target
// uri: 'https://api.us.poppulo-app.com/graphql'
uri: 'https://api.eu.poppulo-app.com/graphql',
});
const authLink = setContext((_, { headers }) => {
function getToken() {
//ToDo: For development purposes, an API access can be copied from the developer portal Copy API Token button and pasted here
return 'insert-copied-api-token-here';
}
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
authorization: `Bearer ${getToken()}`,
'x-channel-id': 'react',
'x-channel-version': '1.2.3',
},
};
});
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache(),
});
ReactDOM.render(
<React.StrictMode>
<ApolloProvider client={client}>
<App />
</ApolloProvider>
</React.StrictMode>,
document.getElementById('root')
);
Example Application
Now that we know how to configure our client, we can start building out an example react app.
First, run the following command to generate a typescript react app. Further information on this command can be found here.
npx create-react-app my-app --template typescript
An example react application should be generated for you to modify.
We need to install the apollo client dependencies.
yarn add @apollo/client graphql
yarn add --dev @types/graphql
Next we can modify index.tsx
file to create the client, and use ApolloProvider
to make it available to the rest of the application.
import { setContext } from '@apollo/client/link/context';
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { ApolloClient, ApolloProvider, HttpLink, InMemoryCache } from '@apollo/client';
const httpLink = new HttpLink({
// ToDo: Confirm which region your enterprise account is hosted in and comment in the correct API you wish to target
// uri: 'https://api.us.poppulo-app.com/graphql'
uri: 'https://api.eu.poppulo-app.com/graphql',
});
const authLink = setContext((_, { headers }) => {
function getToken() {
//ToDo: For development purposes, an API access can be copied from the developer portal Copy API Token button and pasted here
return 'insert-copied-api-token-here';
}
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
authorization: `Bearer ${getToken()}`,
'x-channel-id': 'react',
'x-channel-version': '1.2.3',
},
};
});
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache(),
});
ReactDOM.render(
<React.StrictMode>
<ApolloProvider client={client}>
<App />
</ApolloProvider>
</React.StrictMode>,
document.getElementById('root')
);
As we have the client injected through the application via ApolloProvider
, we can use useQuery to fetch information from the api.
const TEST_QUERY = gql`
query myQuery {
getPosts {
totalCount
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
edges {
node {
id
author
body
title
status
}
cursor
}
}
}
`;
const { error, loading, data } = useQuery(TEST_QUERY);
The full app.tsx
file should look something like the following:
import { gql, useQuery } from '@apollo/client';
import React from 'react';
import logo from './logo.svg';
import './App.css';
function TestComponent() {
const TEST_QUERY = gql`
query myQuery {
getPosts {
totalCount
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
edges {
node {
id
author
body
title
status
}
cursor
}
}
}
`;
const { error, loading, data } = useQuery(TEST_QUERY);
if (loading) {
return <p>Loading...</p>;
}
if (error) {
return <p>Error :(</p>;
}
// @ts-ignore
return data.getPosts.edges
.map((edge) => edge.node)
.map(({ id, title }) => (
<div key={id}>
<p>
{id}: {title}
</p>
</div>
));
}
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<TestComponent />
</header>
</div>
);
}
export default App;
With the setup complete - in the project directory - you can now run:
yarn start
This runs the app in the development mode, and you can open http://localhost:3000 to view the app in the browser.
Optional/Advanced: Generate typescript types
To make the query results a bit easier to work with, we can generate a typescript type for them using apollo's CLI client.
yarn add apollo --dev
With a copied API access token for the bearer token, we can run the following command to download the schema.
npx apollo client:download-schema schema.graphql --endpoint=https://api.[eu|us].poppulo-app.com/graphql --header="Authorization: Bearer TOKEN"
Run the following command to generate types
npx apollo client:codegen --localSchemaFile=schema.graphql --target=typescript
This should create two files for you __generated__/globalTypes.ts
and src/__generated__/myQuery.ts
.
We can now update our TestComponent to use the new types
function TestComponent() {
const TEST_QUERY = gql`
query myQuery {
getPosts {
totalCount
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
edges {
node {
id
author
body
title
status
}
cursor
}
}
}
`;
const { error, loading, data } = useQuery<myQuery>(TEST_QUERY);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return (
<div>
{
data?.getPosts.edges
.filter(edge => !!edge)
.map(edge => edge as myQuery_getPosts_edges)
.map(edge => edge.node)
.filter(node => !!node)
.map(node => node as myQuery_getPosts_edges_node)
.map(({ id, title }) => (
<div key={id}>
<p>
{id}: {title}
</p>
</div>
))
}
</div>
);
}
As you can see, we need to do some filtering to ensure that our code is set up to handle undefined values gracefully.
Next steps
For a more complete set of example feeds GraphQL queries to build on, see the following link: