Empty subscriber list while channel subscribers count isn't zero - youtube-api

Summary
I'm trying to get a list of channel subscribers, but sometimes I get empty response for specific channels with subscriber count > 0.
Details
Following this YouTube Data API documentation,
I'm trying to receive a list of the channel subscriptions, however did received empty list. This is not reproducible for all channels, but it is this channel -- UCWjFX5qjtUCF4Xr-Z4q0h9w.
I'm using this command to get the current subscribers:
curl \
'https://youtube.googleapis.com/youtube/v3/channels?part=snippet%2CcontentDetails%2Cstatistics&key=XXXXX&mine=true' \
--header 'Authorization: Bearer XXXXXX' \
--header 'Accept: application/json' \
--compressed
The API response is:
{
"kind": "youtube#channelListResponse",
"etag": "XXXXpU",
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 5
},
"items": [
{
"kind": "youtube#channel",
"etag": "XXXXXXXaU",
"id": "UCWjFX5qjtUCF4Xr-Z4q0h9w",
"snippet": {....},
"contentDetails": {..},
"statistics": {
...
"subscriberCount": "5",
}
}
]
}
and then try to list the subscriptions:
curl \
'https://youtube.googleapis.com/youtube/v3/subscriptions?part=snippet,id,subscriberSnippet,contentDetails&key=XXXXXX&mine=true' \
--header 'Authorization: Bearer XXXXXX' \
--header 'Accept: application/json' \
--compressed
with the JSON response:
{
"kind": "youtube#SubscriptionListResponse",
"etag": "XXXXX3i0vIY",
"pageInfo": {
"totalResults": 0,
"resultsPerPage": 5
},
"items": []
}

Update the privacy settings in channel settings.

That happens because when invoking the Subscriptions.list with the request parameter mine set to true, you'll obtain a number of channel to which you -- that channel owner -- have subscribed:
mine (boolean)
This parameter can only be used in a properly authorized request. Set this parameter's value to true to retrieve a feed of the authenticated user's subscriptions.
But a channel's statistics.subscriberCount is counting the number of other YouTube users that subscribed to the respective channel:
statistics.subscriberCount (unsigned long)
The number of subscribers that the channel has. This value is rounded down to three significant figures. Please see the Revision History or the YouTube Help Center for more details about how subscriber counts are rounded.
For the other way around -- i.e. for a list of channels that are subscribers of your channel -- there are two other request parameters: myRecentSubscribers and mySubscribers.

Related

Getting names from geo_target_constant in a Ad report

I am using ads API for getting the spends based on state names of USA.
The below query gives segments.geo_target_state will be returned as an ID instead of name
How can I combine this query with
SELECT
geo_target_constant.name,
geo_target_constant.canonical_name
FROM geo_target_constant
WHERE geo_target_constant.id = <<OBTAINED ID FROM THE BELOW QUERY>>
curl "https://googleads.googleapis.com/v10/customers/${CUSTOMER_ID}/googleAds:searchStream" \
--header "Content-Type: application/json" \
--header "developer-token: ${DEVELOPER_TOKEN}" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data '{
"query": "
SELECT
campaign.name,
segments.geo_target_state,
metrics.cost_micros
FROM geographic_view
WHERE
geographic_view.location_type = LOCATION_OF_PRESENCE
AND segments.date BETWEEN 20220101 AND 20220430
"
}'
That is geoTargetConstants/21136 must be decoded to
"name": "New Jersey",
"results": [
{
"campaign": {
"resourceName": "customers/1234/campaigns/1234",
"name": "Display - macines - Leads Display Campaign Test - AA"
},
"metrics": {
"costMicros": "66664821"
},
"segments": {
"geoTargetState": "**geoTargetConstants/21136**"
},
"geographicView": {
"resourceName": "customers/6383148790/geographicViews/2840~LOCATION_OF_PRESENCE"
}
},
If you want to use the API to lookup the geo target constant name you will have to issue another search request using the query you provided.
This is likely okay in one off scenarios but breaks down quickly if you need to retrieve multiple geo target constants.
What I have do to resolve this is pull the list of geo targets, see: https://developers.google.com/google-ads/api/reference/data/geotargets, and store them locally in a database. Then I can pull the name from a must faster source.

calling activities:list fails on using parameter `mine=true` (Youtube Data API V3)

I have been trying to use the API to retrieve my activities but I'm receiving the following JSON error.
{
"error": {
"code": 403,
"message": "The request is not properly authorized.",
"errors": [
{
"message": "The request is not properly authorized.",
"domain": "youtube.activity",
"reason": "forbidden"
}
]
}
}
, although I use https://www.googleapis.com/youtube/v3/activities?mine=true&key={my_api_key}&part=contentDetails and I use OAuth2 client to get an access token which I use on calling the API.
I tried to use the samples but I'm receiving the same error.
Is this a bug or I'm doing something wrong?
More details
I use the given link in postman with the GET method and I put a valid access token in the token field with TYPE=OAuth2 and Prefix=Bearer
According to the official specification of the Activities.list API endpoint, for to be able to use its mine request parameter, you have to issue the call to the endpoint while passing to it proper credentials:
mine (boolean)
This parameter can only be used in a properly authorized request. Set this parameter's value to true to retrieve a feed of the authenticated user's activities.
Therefore, using an API key is not sufficient (neither is required when issuing a properly authorized request).
Do note that the JSON error response obtained from the API agrees entirely with the specification quoted above.
According to the official (programming language agnostic) procedure, for to obtain a valid fresh access token from the API, issue a simple curl instance as follows:
$ curl \
--data 'grant_type=refresh_token' \
--data-urlencode "client_id=$CLIENT_ID" \
--data-urlencode "client_secret=$CLIENT_SECRET" \
--data-urlencode "refresh_token=$REFRESH_TOKEN" \
https://oauth2.googleapis.com/token
Above, $CLIENT_ID and $CLIENT_SECRET are the values of the corresponding properties of your client secrets JSON file you've got from Google's developers console. The $REFRESH_TOKEN is your (long-lived) refresh token you've obtained upon running a successful OAuth2 authentication/authorization flow.
The output obtained from curl when successful would look like:
{
"access_token": "...",
"expires_in": 3599,
"scope": "...",
"token_type": "Bearer"
}
A call to the Activities.list endpoint as yours above using curl is immediate:
$ curl \
--header "Authorization: Bearer $ACCESS_TOKEN" \
'https://www.googleapis.com/youtube/v3/activities?mine=true&part=contentDetails&maxResults=25'
The parameter $ACCESS_TOKEN above is your freshly obtained valid access token; the output of curl would look like:
{
"kind": "youtube#activityListResponse",
"etag": "...",
"items": [
{
"kind": "youtube#activity",
"etag": "...",
"id": "...",
"contentDetails": {
...
}
},
...
],
"pageInfo": {
"totalResults": ...,
"resultsPerPage": 25
}
}
For to run the above curl commands on a Windows machine under CMD.exe -- assuming that you've substitued the $-variables yourself manually --, do replace the backslash character at the end of each line above with the caret character, ^. The percent character % should be doubled, i.e. should be replaced with %%, and the single quote characters ' should be replaced with double-quote characters ".

Retrieves a list of apps that results of searching by the given term on app store or iTunes store

I am using Node.js module to scrape application data from the iTunes/Mac App Store. My purpose is find then app ranking in search result for particular keyword search.
https://github.com/facundoolano/app-store-scraper
Till today, This module was giving proper app ranking on search results by keyword but suddenly It completely shows different search result than app store in iPhone or Mac.
Does anyone know that There are any changes from apple side?
Module uses below apple url to find the search result.
const BASE_URL = 'https://itunes.apple.com/WebObjects/MZStore.woa/wa/search?clientApplication=Software&media=software&term=';
Does any changes in above URL?
Here is the official api documentation for itunes search api - https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/
Here is an example below for the search you are trying to do:
curl -X GET \
'https://itunes.apple.com/search?clientApplication=Software&media=software&term=Misfits%20Emoji' \
-H 'Accept: */*' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'Cache-Control: no-cache' \
-H 'Connection: keep-alive' \
-H 'Host: itunes.apple.com' \
-H 'Postman-Token: 06880666-0bb8-4b43-80ed-53e4300444cd,004c0b3c-dffd-4b3d-90e3-e36167e2a127' \
-H 'User-Agent: PostmanRuntime/7.20.1' \
-H 'cache-control: no-cache'
For the example, I have used this application to search https://apps.apple.com/us/app/misfits-emoji/id1172889389 and it is the first item returned in the response.
Response:
{
"resultCount": 1,
"results": [{
"artistViewUrl": "https://apps.apple.com/us/developer/fan-si-inc/id932552952?uo=4",
"artworkUrl60": "https://is2-ssl.mzstatic.com/image/thumb/Purple71/v4/f5/ac/81/f5ac813b-2c60-5739-023d-fca28a4b5fb5/source/60x60bb.jpg",
"artworkUrl100": "https://is2-ssl.mzstatic.com/image/thumb/Purple71/v4/f5/ac/81/f5ac813b-2c60-5739-023d-fca28a4b5fb5/source/100x100bb.jpg",
"screenshotUrls": ["https://is2-ssl.mzstatic.com/image/thumb/Purple71/v4/95/8b/4c/958b4c46-b4d8-f035-d723-ef764131a1f9/pr_source.png/392x696bb.png", "https://is3-ssl.mzstatic.com/image/thumb/Purple71/v4/ab/c0/a2/abc0a2f7-30c3-6f4f-2fa9-f2ccf4b15912/pr_source.png/392x696bb.png"],
"ipadScreenshotUrls": [],
"appletvScreenshotUrls": [],
"artworkUrl512": "https://is2-ssl.mzstatic.com/image/thumb/Purple71/v4/f5/ac/81/f5ac813b-2c60-5739-023d-fca28a4b5fb5/source/512x512bb.jpg",
"isGameCenterEnabled": false,
"advisories": [],
"supportedDevices": ["iPad2Wifi-iPad2Wifi", "iPad23G-iPad23G", "iPhone4S-iPhone4S", "iPadThirdGen-iPadThirdGen", "iPadThirdGen4G-iPadThirdGen4G", "iPhone5-iPhone5", "iPodTouchFifthGen-iPodTouchFifthGen", "iPadFourthGen-iPadFourthGen", "iPadFourthGen4G-iPadFourthGen4G", "iPadMini-iPadMini", "iPadMini4G-iPadMini4G", "iPhone5c-iPhone5c", "iPhone5s-iPhone5s", "iPadAir-iPadAir", "iPadAirCellular-iPadAirCellular", "iPadMiniRetina-iPadMiniRetina", "iPadMiniRetinaCellular-iPadMiniRetinaCellular", "iPhone6-iPhone6", "iPhone6Plus-iPhone6Plus", "iPadAir2-iPadAir2", "iPadAir2Cellular-iPadAir2Cellular", "iPadMini3-iPadMini3", "iPadMini3Cellular-iPadMini3Cellular", "iPodTouchSixthGen-iPodTouchSixthGen", "iPhone6s-iPhone6s", "iPhone6sPlus-iPhone6sPlus", "iPadMini4-iPadMini4", "iPadMini4Cellular-iPadMini4Cellular", "iPadPro-iPadPro", "iPadProCellular-iPadProCellular", "iPadPro97-iPadPro97", "iPadPro97Cellular-iPadPro97Cellular", "iPhoneSE-iPhoneSE", "iPhone7-iPhone7", "iPhone7Plus-iPhone7Plus", "iPad611-iPad611", "iPad612-iPad612", "iPad71-iPad71", "iPad72-iPad72", "iPad73-iPad73", "iPad74-iPad74", "iPhone8-iPhone8", "iPhone8Plus-iPhone8Plus", "iPhoneX-iPhoneX", "iPad75-iPad75", "iPad76-iPad76", "iPhoneXS-iPhoneXS", "iPhoneXSMax-iPhoneXSMax", "iPhoneXR-iPhoneXR", "iPad812-iPad812", "iPad834-iPad834", "iPad856-iPad856", "iPad878-iPad878", "iPadMini5-iPadMini5", "iPadMini5Cellular-iPadMini5Cellular", "iPadAir3-iPadAir3", "iPadAir3Cellular-iPadAir3Cellular", "iPodTouchSeventhGen-iPodTouchSeventhGen", "iPhone11-iPhone11", "iPhone11Pro-iPhone11Pro", "iPadSeventhGen-iPadSeventhGen", "iPadSeventhGenCellular-iPadSeventhGenCellular", "iPhone11ProMax-iPhone11ProMax"],
"kind": "software",
"features": [],
"contentAdvisoryRating": "4+",
"trackCensoredName": "Misfits Emoji",
"languageCodesISO2A": ["EN"],
"fileSizeBytes": "32731136",
"sellerUrl": "http://fan.si",
"averageUserRatingForCurrentVersion": 3.5,
"userRatingCountForCurrentVersion": 4,
"trackViewUrl": "https://apps.apple.com/us/app/misfits-emoji/id1172889389?uo=4",
"trackContentRating": "4+",
"currentVersionReleaseDate": "2016-11-21T17:30:21Z",
"releaseNotes": "Updated icons.",
"isVppDeviceBasedLicensingEnabled": true,
"formattedPrice": "$0.99",
"trackId": 1172889389,
"trackName": "Misfits Emoji",
"primaryGenreName": "Entertainment",
"genreIds": ["6016", "6002"],
"primaryGenreId": 6016,
"sellerName": "Fansi Inc",
"releaseDate": "2016-11-17T18:12:35Z",
"minimumOsVersion": "8.0",
"currency": "USD",
"version": "1.0.1",
"wrapperType": "software",
"artistId": 932552952,
"artistName": "Fan.si Inc.",
"genres": ["Entertainment", "Utilities"],
"price": 0.99,
"description": "Social Club Misfits present this very rare emoji collection featuring dozens of new emoticon pictures and exclusive gifs. Satisfy all you communication needs with pizza, pugs, pineapples, and so much more!",
"bundleId": "si.fan.socialmisfits-emoji"
}]
}

Cumulocity - Send Measurement/Alarm/Event using external ID via HTTP

I've been recently exploring Cumulocity and managed to use the external ID to send data (measurements/alarms/events) via MQTT. Its well documented and pretty straight forward.
But I cant find how to send data (measurement/alarm/event) using ExternalID instead of source.
For example, here is how POST of a measurement looks like if you know ClientID of device:
curl -X POST \
https://myTenant.cumulocity.com/measurement/measurements \
-H 'Accept: application/vnd.com.nsn.cumulocity.measurement+json' \
-H 'Authorization: Basic mytoken' \
-H 'Content-Type: application/json' \
-d '{
"c8y_TemperatureMeasurement": {
"T": {
"value": 25,
"unit": "C" }
},
"time":"2019-03-07T10:03:14.000+11:00",
"source": {
"id":"1234567" },
"type": "c8y_TemperatureMeasurement"
}'
Is there a way to replace that "source": {"id":"1234567" }, with external ID?
What would the request look like?
As of today, this is not possible:
Instead you have to first convert the externalID to the source id once (e.g. when the device is booted its done as first actions). Afterwards send all requests (e.g. POSTs to create measurements/alarms/events) using this retrieved sourceID.
This is also described in the Device SDK for HTTP here: https://cumulocity.com/guides/device-sdk/rest#step-1-check-if-the-device-is-already-registered .
Thanks for the good feedback on the documentation!

Find the youtube channel id for Google+ development or any other reason

Find the channel id for a youtube channel in case you want to subscribe to it or for any other purpose.
Let's say you want to let the users subscribe to the client application's youtube channel by clicking subscribe. The user would have to sign in to Google+ and then run an api request to subscribe. So for this scenario you would need the channel id.
Please note that the new way of doing things is Google+ instead of GData
Go to the following link and replace the username of that channel[foofightersVEVO with the username of that channel]
https://developers.google.com/apis-explorer/#p/youtube/v3/youtube.search.list?part=id&maxResults=1&q=foofightersVEVO&type=channel&_h=3&
execute the query and look at the api response:
GET https://www.googleapis.com/youtube/v3/search?part=id&maxResults=1&q=foofightersVEVO&type=channel&key={YOUR_API_KEY}
X-JavaScript-User-Agent: Google APIs Explorer
{
"kind": "youtube#searchListResponse",
"etag": "\"2vd4g3cVsHAtTjJSdUMaBo1PBVE/6Ux-QcH6OQdn3t89j3y5z9RQhv0\"",
"pageInfo": {
"totalResults": 161878,
"resultsPerPage": 1
},
"nextPageToken": "CAEQAA",
"items": [
{
"kind": "youtube#searchResult",
"etag": "\"2vd4g3cVsHAtTjJSdUMaBo1PBVE/Q9-widOQXafayJk0l2DV9nrMYO0\"",
"id": {
"kind": "youtube#channel",
"channelId": "UCGRjJrpD2bmk9Ilq6nq80qg"
}
}
]
}
Note the channelId there. Hope this helps.

Resources